Making shared_ptr lose ownership of memory

狂风中的少年 提交于 2019-12-10 09:23:27

问题


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

回答1:


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?




回答2:


You could use a unique_ptr, which is anyhow better suited for passing memory around:

unique_ptr<MyProto> myProtoSharedPtr = // create MyPorto object

CollectionProto collectionProto;

// unique_ptr::release returns the pointer and
// releases the ownership of the MyProto object
collectionProto.mutable_my_proto().AddAllocated(myProtoSharedPtr.release());

std::string serialization = collectionProto.SerializeAsString();



回答3:


You will need to provide std::shared_ptr with a custom deleter (See constructor 4). Then you can define the deleter to do what you want. Including, not destroy your object.

Note 1: I don't recomend using shared_ptr here, but this is a way to do what you want.

Note 2: If you use make_shared to create your objects you will likely run into trouble correctly deleting the memory once the last shared_ptr is removed.




回答4:


Rather than copying, you could move it into a newed object.

MyProto * myProto = new MyProto(std::move(*mySharedProto));

CollectionProto collectionProto;
collectionProto.mutable_my_proto().AddAllocated(myProto);

You could also investigate whether CollectionProto will accept it by value

CollectionProto collectionProto;
collectionProto.mutable_my_proto().Add(std::move(*mySharedProto));



回答5:


You could use std::move when you want to transfer the ownership, see the following example

#include <iostream>
#include <memory>
void take_ownership(std::shared_ptr<int> ptr){
std::cout<<ptr.use_count()<<" == 2\n";
} // destroying it


int main()
{
std::shared_ptr<int> p=std::make_shared<int>(1);
std::shared_ptr<int> p2(p);
//p is valid                                                                                                                                                                                                                                                                              
if(!p.get())
std::cout<<"error\n";
else
std::cout<<"OK\n";

//use p, p2

take_ownership(std::move(p));
//p is invalid                                                                                                                                                                                                                                                                            
if(!p.get())
std::cout<<"OK\n";
else
std::cout<<p.use_count()<<" error\n";

}


来源:https://stackoverflow.com/questions/50831775/making-shared-ptr-lose-ownership-of-memory

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