问题
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