Delete std::shared_ptr without destroying the managed object?

一曲冷凌霜 提交于 2019-12-12 13:45:50

问题


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?


回答1:


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.




回答2:


std::shared_ptr doesn't give up the ownership so you have to keep it somewhere in your class to make sure the pointer doesn't get deleted. Still, you could use the acquired shared_ptr instead of storing raw pointer. Raw pointers almost always is a bad choice.




回答3:


It's not possible.

Even if you take care of object destruction in container destructor, you can't guarantee that no other object have std::shared_ptr holding pointer to that object (in this case you will see double free error).

If object lifetime is managed by std::shared_ptr (without special deleter) then you can control object lifetime only through std::shared_ptr and std::weak_ptr.




回答4:


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();
}


来源:https://stackoverflow.com/questions/28922488/delete-stdshared-ptr-without-destroying-the-managed-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!