使shared_ptr失去内存的所有权

时间:2018-06-13 07:49:03

标签: c++ c++11 protocol-buffers shared-ptr

我传了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

5 个答案:

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