【问题标题】:std::shared_ptr deep copy objectstd::shared_ptr 深拷贝对象
【发布时间】:2013-11-14 03:55:15
【问题描述】:

找不到太多关于 C++11 的内容,但只能在 boost 上找到。

考虑以下类:

class State
{
   std::shared_ptr<Graph> _graph;

 public:

    State( const State & state )
    {
        // This is assignment, and thus points to same object
        this->_graph = std::make_shared<Graph>( state._graph ); 

        // Deep copy state._graph to this->_graph ?
        this->_graph = std::shared_ptr<Graph>( new Graph( *( state._graph.get() ) ) );

        // Or use make_shared?
        this->_graph = std::make_shared<Graph>( Graph( *( state._graph.get() ) ) );
    }   
};

假设 class Graph 确实有一个复制构造函数:

Graph( const Graph & graph )

我不想让 this->_graph 指向/共享同一个对象! 相反,我希望 this->_graph 将对象从 state._graph 深复制到我自己的 this->_graph 副本中。 p>

上面的方法是正确的吗?

Documentation of std::make_shared 注意到:

此外,f(shared_ptr(new int(42)), g()) 会导致内存泄漏 如果 g 抛出异常。如果 make_shared 是,则此问题不存在 用过。

还有其他方法可以解决这个问题,更安全或更可靠吗?

【问题讨论】:

  • 如果您希望每个对象指向自己的Graph,是否有理由使用shared_ptr?似乎另一种指针类型会更合适,就像将 Graph 作为直接子对象一样。
  • 是的,它们属于其他类。但是在这种特殊情况下,我真的需要一个副本,而不是像我打算更改它那样共享给定的对象,而不希望更改原始对象。你建议我改用 unique_ptr 吗?
  • 这将是我的建议之一,但如果对象真的是共享的,那么还有很多其他好的方法。

标签: c++11 shared-ptr deep-copy


【解决方案1】:

如果您想在复制对象时复制Graph 对象,您始终可以定义复制构造函数和赋值运算符来做到这一点:

State::State(const State& rhs) : _graph(std::make_shared(*rhs._graph)) {
   // Handled by initializer list
}
State::State(State&& rhs) : _graph(std::move(rhs._graph)) {
   // Handled by initializer list
}
State& State::operator= (State rhs) {
    std::swap(*this, rhs);
    return *this;
}

希望这会有所帮助!

【讨论】:

  • 我现在更加好奇了。您拥有的第一个 Copy 构造函数只是分配了相同的图,不是吗?而第二个使用move,它会移动而不是复制对象,不是吗?
  • 复制构造函数将_graph初始化为一个std::shared_ptr,它指向一个全新的Graph对象,该对象初始化为原始图的副本。这意味着它最终指向一个新的Graph,与原始图形分开。在移动构造函数中,我们只是将现有的shared_ptr 移出现有的State 对象,因为该对象将不再被使用。
  • 附加说明:_graph = std::make_shared&lt;Graph&gt;( * state._graph ); (注意星号!) 将调用 Graph 的复制 ctor,因为 make_shared&lt;T&gt; 将参数传递给 ctor,并且 @ 987654332@ 提供对由 shared_ptr 管理的对象的引用。一个引用自己类型的 ctor 将是 copy-ctor(假设有一个)。如果您只想与另一个 shared_ptr 共享所有权,那么它就是_graph(state._graph)(shared_ptr 的副本)。当您想要一个新的T 对象(包装在一个shared_ptr 中)时,您只需要make_shared
猜你喜欢
  • 2011-05-04
  • 2015-09-14
  • 1970-01-01
  • 1970-01-01
  • 2012-06-19
  • 2019-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多