I have a shared_ptr<MyProto>
which I pass around. Eventually, in certain situations, I want pass the raw pointer to a function which then becomes the memory owner. In those cases the shared_ptr
isn't responsible anymore for freeing the memory because the function I call took ownership. How do I get the shared_ptr
to lose ownership?
The reason I want to have the shared_ptr
lose ownership is that I want to use protocol buffer's AddAllocated functionality which takes an already allocated pointer and assumes ownership of it.
Example:
shared_ptr<MyProto> myProtoSharedPtr = // by this point this is the last reference to the heap allocated MyProto
// I want to add it to a collection and serialize the collection without copying
CollectionProto collectionProto;
collectionProto.mutable_my_proto().AddAllocated(myProtoSharedPtr.get()); // at this point collectionProto took ownership of the memory
std::string serialization = collectionProto.SerializeAsString();
// bad: myProtoSharedPtr.get() will be freed twice
And the memory pointed by the underlying pointer is deleted when:- The reference count becomes zero i.e. the last remaining shared_ptr object is destroyed. The last remaining shared_ptr object owning the pointer is assigned with some other pointer.
shared_ptr objects release ownership on the object they co-own as soon as they themselves are destroyed, or as soon as their value changes either by an assignment operation or by an explicit call to shared_ptr::reset.
shared_ptr maintains a reference count as to how many shared_ptr objects own the same underlying pointer. And the memory pointed by the underlying pointer is deleted when:- The reference count becomes zero i.e. the last remaining shared_ptr object is destroyed.
If a shared_ptr is constructed from an existing pointer that is not shared_ptr the memory for the control structure has to be allocated. This Control block is destroyed and deallocated when the last weak ref goes away. A shared_ptr construction approach takes two steps
I think you can achieve what you want to do by sharing a unique pointer like this:
std::shared_ptr<std::unique_ptr<MyProto>> myProtoSharedUniquePtr;
Accessing it would be more indirect:
(*myProtoSharedUniquePtr)->do_stuff();
But you could take ownership like this:
CollectionProto collectionProto;
collectionProto.mutable_my_proto().AddAllocated(myProtoSharedUniquePtr->release()); // at this point collectionProto took ownership of the memory
std::string serialization = collectionProto.SerializeAsString();
However I would question why you are using a std::shared_ptr
to begin with. The reason to use a std::shared_ptr
is when you have no control over who will be last to access it, so each one gets to keep it alive until they are done. So it would be unusual to be able to guarantee all current std::shared_ptr
instances are no longer in use.
Are you sure a std::unique_ptr
would not be better for your needs?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With