Search code examples
c++cmultidimensional-arrayshared-ptr

c++ - array of shared_ptr


Context:

I try to avoid vectors and replace it with smart pointers as an exercise. The goal is to benefit from smart pointers to avoid memory leaks without relying on vectors, because that is what I want to try now.

The codes below is just a mean to be easily understood.

I want my c++ code to work.

Update : I would like to stick as much as possible with raw c'ish style for IO: please no std::string or c++ streams in general.

The codes:

C version (working):

typedef struct{
    char ** my_arr;
} MyInputs;

...
MyInputs *Doc = malloc(sizeof *Doc);
*Doc->my_arr = malloc(sizeof (*Doc->my_arr) * 2);
Doc->my_arr[0] = malloc(10);
Doc->my_arr[1] = malloc(10);

// Yes, that is stupid to alloc 10 bytes and use only 6 or 5. That is for the example.
memcpy(Doc->my_arr[0],(char*)"Hello\0",6);
memcpy(Doc->my_arr[1],(char*)"Cool\0",5);

printf("%s %s \n",Doc->my_arr[0],Doc->my_arr[1] );
...

C++ version (attempt):

typedef struct {

    std::shared_ptr<char*>my_arr;

}MyInputs;

...

std::shared_ptr<MyInputs> MainDoc (static_cast<MyInputs*>(malloc(sizeof (*MainDoc))),free); 

std::shared_ptr<char*> Z (static_cast<char**>(malloc(sizeof (**MainDoc->my_arr) * 10)),free); 
std::shared_ptr<char> Z[0](static_cast<char*>(malloc(sizeof (char *) * 10)),free); 
memcpy(Z[0].get(), (char*)"salut\0", 6);

cout << Z[0] << endl;

...

The obvious:

In the c++ version, the compiler complains about Z and Z[0] being the same and that there is not match for operator [] in the cout. Well, well, well...

Any ideas that could make the c++ code work that way ? (and again, I know about vectors).


Solution

  • If you insist on using the wrong tool for the job, then you'll want each inner pointer to also be a smart pointer:

    shared_ptr<shared_ptr<char>> my_arr;
    

    You can't simply use malloc to create an array of non-trivial types like shared_ptr; use new:

    my_arr.reset(new shared_ptr<char>[10], [](shared_ptr<char> * p) {delete [] p;});
    

    Then you can assign or reset the elements. shared_ptr doesn't support [], since it's generally not used for arrays, so use get() to get a pointer to the first element:

    my_arr.get()[0].reset(new char[10], [](char * p) {delete [] p;});
    

    Or just replace this gibberish with something sensible

    std::vector<std::string> my_arr {"Hello", "Cool"};