0

I am new to using smart pointers in C++ and my current issue is that I am converting C code to C++ (C++11/14/17) and I am having some problems understanding using shared_ptr with a pointer to pointer. I have derived a toy example which I believe illustrates the problem

Following is the header file

#include <memory>
using std::shared_ptr;

struct DataNode
{
  shared_ptr<DataNode> next;
} ;


 struct ProxyNode
 {
   shared_ptr<DataNode> pointers[5];
 } ;


 struct _test_
 {
   ProxyNode** flane_pointers;
  };

And the actual code test.cpp

#include <stdint.h>
#include "test.h"


shared_ptr<DataNode> newNode(uint64_t key);

shared_ptr<ProxyNode> newProxyNode(shared_ptr<DataNode> node);

int main(void)
{
  // Need help converting this to a C++ style calling
  ProxyNode** flane_pointers = (ProxyNode**)malloc(sizeof(ProxyNode*) * 100000);
  // Here is my attempt (incomplete)
  ProxyNode** flane_pointers = new shared_ptr<ProxyNode> ?
  shared_ptr<DataNode> node = newNode(1000);
  flane_pointers[1] = newProxyNode(node)
} 

shared_ptr<ProxyNode> newProxyNode(shared_ptr<DataNode> node) 
{

  shared_ptr<ProxyNode> proxy(new ProxyNode());
 return proxy;
}

shared_ptr<DataNode> newNode(uint64_t key) 
{
 shared_ptr<DataNode> node(new DataNode());
 return node;
}

I am getting these compiler errors -

 test.cpp: In function ‘int main()’:
 test.cpp:12:42: error: cannot convert ‘std::shared_ptr<ProxyNode>’ to  ‘ProxyNode*’ in assignment
  flane_pointers[1] = newProxyNode(node)

Compiled with

  g++ -c -g test.h test.cpp

g++ version is 7.3.0 (on Ubuntu 18)

I need help converting the C style malloc allocation with a C++ style calling for a pointer to a pointer and then how to fix the compiler errors. My apologies if it looks like I am missing something obvious.

1 Answer 1

2

If this ProxyNode** flane_pointers; is supposed to be a matrix of ProxyNode then the most simple approach would be to create vector of vectors containing ProxyNode like this:

struct DataNode
{
    std::shared_ptr<DataNode> next;
};


struct ProxyNode
{
    // here instead of C style array you can use std::array
    std::shared_ptr<DataNode> pointers[5];
};

TEST(xxx, yyy) {
    std::vector<std::vector<ProxyNode> > matrixOfProxyNodes;
    // insert empty vector of ProxyNode
    matrixOfProxyNodes.push_back(std::vector<ProxyNode>());
    // insert ProxyNode to the first vector of ProxyNodes
    matrixOfProxyNodes[0].push_back(ProxyNode());
    // insert shared_ptr to DataNode in position 0, 0 of matrix of ProxyNodes
    matrixOfProxyNodes[0][0].pointers[0] = std::make_shared<DataNode>();
}

If you really need the pointer to pointer (but I really don't see the purpose for that) you can do:

    // create shared pointer to shared pointer to ProxyNode
    // and initialize it to nullptr
    std::shared_ptr<std::shared_ptr<ProxyNode> > ptr2ptr2ProxyNode(nullptr);
    // dynamically create new shared_ptr to ProxyNode
    ptr2ptr2ProxyNode.reset(new std::shared_ptr<ProxyNode>(nullptr));
    // dynamically create ProxyNode
    ptr2ptr2ProxyNode->reset(new ProxyNode());
    (*ptr2ptr2ProxyNode)->pointers[0] = std::make_shared<DataNode>();

Note that std::shared_ptr does not behave exactly as raw pointer, for example you shouldn't allocate the memory for shared_ptr with operator new[]. Here is explained why.

Also I see that you probably want to implement some kind of list or other chain. std::shared_ptr can suffer from cyclic dependency, so be careful and use std::weak_ptr when needed.

Sign up to request clarification or add additional context in comments.

6 Comments

flane_pointers is not a matrix of ProxyNode(s) but a 1-D array of it yes.
I do not think I can use vectors because the legacy code needs to use indices to get elements. So an array based approach is necessary. Can you explain what ptr2ptr2ProxyNode is ? It is not clear.
For sure you can use std::vector. They are compatible with your legacy code using indices, offsets, addresses of elements and so on. This is explained here.
Thanks. I will give it a try. Is that a best practice though ? To use vector and search with indices, offsets and addresses ?
The best practice is to define a class with the interface that serves exactly your purpose (but you need to understand that purpose first, which is not always obvious when you translate code from C). For the beginning it is a good practice to use std::vector instead of C-style T* arr; array. std::vector provides you the interface to access elements with square brackets operator elem[i]; iterators (that have pointer syntax) or even C-style access to underlying data
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.