Making shared_ptr lose ownership of memory

放肆的年华 提交于 2019-12-05 15:33:49

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?

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

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.

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

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";

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