std :: shared_ptr的唯一副本

时间:2014-01-10 14:07:39

标签: c++ c++11

我有一个对象(我们称之为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
  }
}

4 个答案:

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

一般情况下不可能。可能有两种情况:

  1. 存储在bar中的对象是Bar类型,而不是从Bar继承的类。然后只使用复制构造函数(如果它可用):

    bar = std::make_shared<Bar>(*bar);

  2. 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”。