使shared_ptr失去对内存的所有权



我有一个shared_ptr<MyProto>,我把它传来传去。最终,在某些情况下,我希望将原始指针传递给一个函数,该函数随后成为内存所有者。在这些情况下,shared_ptr不再负责释放内存,因为我调用的函数获得了所有权。如何让shared_ptr失去所有权?

我想让shared_ptr失去所有权的原因是我想使用协议缓冲区的 AddAssigned 功能,该功能采用已分配的指针并承担其所有权。

例:

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

我认为您可以通过分享独特的 像这样的指针

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不会更适合您的需求吗?

您可以使用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();

您需要为std::shared_ptr提供自定义删除器(请参阅构造函数 4(。然后,您可以定义删除程序以执行所需的操作。包括,而不是破坏您的对象。

注意1:我不建议在这里使用shared_ptr,但这是一种做你想做的事的方法。

注意 2:如果使用make_shared创建对象,则在删除最后一个shared_ptr后,在正确删除内存时可能会遇到问题。

与其复制,不如将其移动到newed 对象中。

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

当您想要转让所有权时,可以使用 std::move,请参阅以下示例

#include <iostream>
#include <memory>
void take_ownership(std::shared_ptr<int> ptr){
std::cout<<ptr.use_count()<<" == 2n";
} // 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<<"errorn";
else
std::cout<<"OKn";
//use p, p2
take_ownership(std::move(p));
//p is invalid                                                                                                                                                                                                                                                                            
if(!p.get())
std::cout<<"OKn";
else
std::cout<<p.use_count()<<" errorn";
}

最新更新