我传了shared_ptr<MyProto>
。最终,在某些情况下,我想将原始指针传递给一个函数,然后该函数成为内存所有者。在这些情况下,shared_ptr
不再负责释放内存,因为我调用的函数取得了所有权。如何让shared_ptr
失去所有权?
我希望shared_ptr
失去所有权的原因是我想使用协议缓冲区的AddAllocated功能,它接受已经分配的指针并假设它的所有权。
示例:
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
答案 0 :(得分:6)
您可以使用unique_ptr
,它无论如何更适合传递内存:
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();
答案 1 :(得分:6)
我认为您可以通过分享 唯一来实现您想要做的事情 指针像这样:
std::shared_ptr<std::unique_ptr<MyProto>> myProtoSharedUniquePtr;
访问它会更间接:
(*myProtoSharedUniquePtr)->do_stuff();
但你可以这样拥有所有权:
CollectionProto collectionProto;
collectionProto.mutable_my_proto().AddAllocated(myProtoSharedUniquePtr->release()); // at this point collectionProto took ownership of the memory
std::string serialization = collectionProto.SerializeAsString();
但是我会质疑为什么你开始使用std::shared_ptr
。使用std::shared_ptr
的原因是当你无法控制谁将最后访问它时,所以每个人都可以保持活着直到它们完成。因此,能够保证所有当前std::shared_ptr
实例不再使用是不常见的。
您确定std::unique_ptr
对您的需求不会更好吗?
答案 2 :(得分:2)
您需要向std::shared_ptr
提供custom deleter(请参阅构造函数4)。然后,您可以定义删除器以执行您想要的操作。包括,不要破坏你的对象。
注1:我不建议在这里使用shared_ptr,但这是一种做你想做的事情。
注意2:如果您使用make_shared
创建对象,则在删除最后一个shared_ptr后,您可能会在正确删除内存时遇到问题。
答案 3 :(得分:1)
如果要转移所有权,可以使用std :: move,请参阅以下示例
#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";
}
答案 4 :(得分:1)
您可以将其移动到new
ed对象中,而不是复制。
MyProto * myProto = new MyProto(std::move(*mySharedProto));
CollectionProto collectionProto;
collectionProto.mutable_my_proto().AddAllocated(myProto);
您还可以调查CollectionProto
是否会按值接受
CollectionProto collectionProto;
collectionProto.mutable_my_proto().Add(std::move(*mySharedProto));