Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delete std::shared_ptr without destroying the managed object?

I'm in the following scenario:

struct container {
    data* ptr;
};

void someFunc(container* receiver /* wants to be filled */) {
    auto myData = createData(); // returns shared_ptr<data>
    receiver->ptr = myData.get();
}

The function that generates that data, and the object that receives it, are part of two different libraries, which I can't modify the source code of. I have to work with these data types, there's nothing I can do about it.

So I have to implement a function that acquires some data, then passes a pointer to that data to an object. My problem is that the function that creates my data, returns a shared_ptr instance to it. The object that needs the data will only accept a raw pointer to it.

As you can see, I call get() on the shared_ptr to get the raw pointer and pass it to the receiving object. If I'm not mistaken, then a shared_ptr decrements the reference count whenever it goes out of scope. So in this case, that means that it would destroy my data as soon as the function returns, since the reference count would reach 0.

So how can I get rid of the shared_ptr instance without destroying the managed object? The object which I pass the data to (illustrated with the "container" struct for simplicity) does take care of the memory cleaning inside its destructor, so I don't need any reference counting or anything like that. I don't want anything to watch over that allocated data anymore (except the object that receives a pointer to it). I want to get rid of the shared_ptr, and only have a raw pointer to the allocated data, which I can pass to the receiving object.

Is that possible?

like image 631
notadam Avatar asked Oct 15 '25 16:10

notadam


2 Answers

static std::map m<data *, std::shared_ptr<data> >;

struct container {
    data* ptr;
};

void someFunc(container* receiver /* wants to be filled */) {
    auto myData = createData(); // returns shared_ptr<data>, I can't do anything about it
    receiver->ptr = myData.get();
    m[receiver->ptr] = myData;
}


void someOtherFunc(container* receiver)
{
  // delete receiver->ptr;
  m.erase(receiver->ptr);
}

This elongates the life of shared_ptr through a map.

like image 51
Mohit Jain Avatar answered Oct 17 '25 05:10

Mohit Jain


The only way I can see out of this (if your design will allow) is to wrap your container:

struct container {
    data* ptr;
};

struct container_wrapper {
    std::shared_ptr<data> ptr; // ensure this lives as long as needed
    container cnt;
};

void someFunc(container_wrapper& receiver /* wants to be filled */) {
    receiver.ptr = createData();
    receiver.cnt.ptr = receiver.ptr.get();
}
like image 23
Galik Avatar answered Oct 17 '25 06:10

Galik