使 shared_ptr 失去内存所有权
Making shared_ptr lose ownership of memory
我有一个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
您可以使用 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
提供 custom deleter(参见构造函数 4)。然后你可以定义删除器来做你想做的事。包括,不破坏你的对象。
注意 1:我不推荐在这里使用 shared_ptr,但这是一种做你想做的方式。
注意 2:如果您使用 make_shared
创建您的对象,您可能会 运行 在删除最后一个 shared_ptr 后正确删除内存。
我认为你可以通过分享一个独特的方式来实现你想做的事情
指针 像这样:
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
不会更好地满足您的需求吗?
当你想转移所有权时,你可以使用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";
}
您可以将其移动到 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));
我有一个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
您可以使用 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
提供 custom deleter(参见构造函数 4)。然后你可以定义删除器来做你想做的事。包括,不破坏你的对象。
注意 1:我不推荐在这里使用 shared_ptr,但这是一种做你想做的方式。
注意 2:如果您使用 make_shared
创建您的对象,您可能会 运行 在删除最后一个 shared_ptr 后正确删除内存。
我认为你可以通过分享一个独特的方式来实现你想做的事情 指针 像这样:
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
不会更好地满足您的需求吗?
当你想转移所有权时,你可以使用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";
}
您可以将其移动到 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));