如何正确复制给定 shared_ptr 的对象

Posted

技术标签:

【中文标题】如何正确复制给定 shared_ptr 的对象【英文标题】:How to properly duplicate an object given its shared_ptr 【发布时间】:2014-05-12 00:21:17 【问题描述】:

我正在尝试复制自定义类 Event 的对象。我有一个指向我从其分配中获得的对象的共享指针:

std::shared_ptr<Event> e = std::make_shared<Event>();

为了获得e 的真实副本(不仅仅是指针的副本),我尝试过:

std::shared_ptr<Event> o = std::make_shared<Event>(*e);

但我不确定这是否是正确的方法,因为如果我删除 e 它似乎也会删除 o...

顺便说一句,我还没有定义复制构造函数Event::Event(const Event &amp;orig),但据我了解,这不是必需的,因为编译器提供了默认的复制构造函数。事件类只包含变量,没有进一步的指针。

【问题讨论】:

好像e也删了o?为何如此?您可以使用 print 语句添加析构函数以查看发生了什么。 您可以将日志放入您的事件析构函数中。例如 std::cout。 【参考方案1】:

您尝试的应该可以正常工作,如果*e 的动态类型是Event,而不是从Event 派生的某个类。 (如果*e 实际上是从Event 派生的对象,那么您将创建一个新的Event(不是派生类型)作为*e 的基类部分的副本,即您将“切片”*e )。

由于您使用make_shared&lt;Event&gt;() 创建了e,因此您知道在这种情况下它确实是Event,因此std::make_shared&lt;Event&gt;(*e) 应该创建一个拥有*e 副本的新shared_ptr

【讨论】:

我遇到了您所描述的问题。如何从另一个 shared_ptr 到 Base 类创建 shared_ptr 到 Base 类的副本,同时保留它实际上是 Derived 类的事实? 到目前为止我最好的解决方案是:'code' std::shared_ptr newBase;派生copyJob = *static_cast(obj.mp_base.get()); newBase = std::make_shared(copiedJob); '\代码' @IronAttorney 使用 ` 进行内联代码标记,而不是“代码”。见***.com/editing-help#comment-formatting【参考方案2】:

std::make_shared 只是一个简单的模板函数,它创建对象,将所有参数传递给构造函数:

template<class T, class... Args>
shared_ptr<T> make_shared(Args&&... args)

  return shared_ptr<T>( new T( std::forward<Args>( args )... ) );

在您的特殊情况下:

std::shared_ptr<Event> o = std::make_shared<Event>(*e);

对象被复制。

如果你的代码是这样的:

void foo() 
    // create new object using default constructor
    std::shared_ptr<Event> e = std::make_shared<Event>();
    // create new object using copy constructor constructor
    std::shared_ptr<Event> o = std::make_shared<Event>(*e);

当然,当它们超出范围时,两个对象都会被销毁。

【讨论】:

make_shared() 是否必须使用新对象进行复制?还是尽可能移动对象? @TheQuantumPhysicist foo() 中的第二行使用复制构造函数创建了一个新对象 - 它不会移动

以上是关于如何正确复制给定 shared_ptr 的对象的主要内容,如果未能解决你的问题,请参考以下文章

将shared_ptr的向量复制到抽象基的派生类中。

使用shared_ptr将基类引用值复制到映射

如何正确使用自定义 shared_ptr 删除器?

访问指向对象指针向量的指针的第一个元素?

shared_ptr的作用

智能指针循环引用--转