我有一个对象(我们称之为X),其他对象可以通过std::shared_ptr
访问它。但是,在某些时候,这些对象需要创建一个唯一的非共享X副本,因为它想要修改它。这在某种程度上类似于写时复制,但由于其他一些细节而不完全相同。
基本上我想有这样的语义:
struct Foo
{
std::shared_ptr<Bar> bar;
void go()
{
// bar.use_count() >= 1
bar.make_this_object_unique();
// bar.use_count() == 1
}
}
答案 0 :(得分:12)
如果你只是想复制对象,并获得一个指向新对象的共享指针,那就是
bar = std::make_shared<Bar>(*bar);
这假设Bar
是目标的实际类型。如果要复制Bar
的任意子类,则需要一个虚函数来复制对象,例如:
struct Bar {
virtual std::shared_ptr<Bar> clone() = 0;
};
struct SomeKindOfBar : Bar {
virtual std::shared_ptr<Bar> clone() {
return std::make_shared<SomeKindOfBar>(*this);
}
};
bar = bar->clone();
您可能希望测试bar.unique()
以确定是否需要副本。
答案 1 :(得分:2)
一般情况下不可能。可能有两种情况:
存储在bar中的对象是Bar类型,而不是从Bar继承的类。然后只使用复制构造函数(如果它可用):
bar = std::make_shared<Bar>(*bar);
Bar或其任何基类以虚拟函数的形式提供克隆功能,创建新分配的副本:
bar = std::shared_ptr<Bar>(bar->Clone());
答案 2 :(得分:1)
您可以执行类似
的操作bar = shared_ptr<Bar>(new Bar(*bar));
您需要做的是对底层对象执行正确的复制,因为有两个shared_ptr实例管理相同的内存是行不通的。
答案 3 :(得分:1)
template<typename T>
std::shared_ptr<T>& cow_ptr( std::shared_ptr<T>& t ) {
if (t && !t.unique())
t = std::make_shared<T>( *t );
return t;
}
为T
提供了写时复制功能。如果实际上不是t
,则会对T
进行切片。
使用是:
struct Foo
{
std::shared_ptr<Bar> bar;
void go()
{
cow_ptr(bar);
}
}
您甚至可以直接使用它,例如cow_ptr(bar)->blah()
。
cow
代表“写作时复制”。 cow_ptr
代表“moo”。