为什么从引用创建共享指针会复制对象?

时间:2017-08-07 15:09:31

标签: c++ copy pass-by-reference shared-ptr

我打算让一个构造函数接受引用,然后创建指向作为引用传递的对象的指针,并将这些指针存储在一个字段中。但是,由于某种原因,我这样做,副本正在创建,我不明白为什么:

delete[]

我在这里缺少什么?复制发生在哪里?为什么?

3 个答案:

答案 0 :(得分:2)

原因是std::make_shared<T>(t)make_shared将调用T的构造函数,该构造函数接受它所给出的参数。你可以通过引用给它一个T左值。

当然,调用复制构造函数。这是一件好事。如果你创建了一个共享指针到你传递的对象,你的代码可能会是一堆未定义的行为。

我建议您通过智能指针接受参数。它使您的类的用户可以从API本身清楚地了解所有权语义。

答案 1 :(得分:2)

  

我在这里缺少什么?复制发生在哪里?为什么?

从字面上回答问题,来自cppreference.com

  

template< class T, class... Args >   shared_ptr<T> make_shared( Args&&... args );   构造一个T类型的对象,并使用std::shared_ptr将其args包装为T的构造函数的参数列表。

在您的情况下,std::make_shared<T>(t)tT&)会调用T::T(T const&)并构建t副本。一个不正确的解决方案是在没有std::shared_ptr的帮助下自己创建std::make_shared ...但在这种情况下,您将创建指向可能静态分配的对象的智能指针。这是,就像 Undefined Behavior 那样糟糕。

更好的解决方案是简单地避免创建通过引用传递的对象的智能指针,因为它可能会给调用者带来惊喜。更好地采取智能指针:

C(std::shared_ptr<T> t, std::shared_ptr<Types> ...args) { /* ... */ }

答案 2 :(得分:2)

std::make_shared<T>分配一大块内存,足以存储类型为T的对象(如果有的话,用传递的参数初始化它),并附加一个控制块来管理共享所有权(如保持对象引用计数等。)。

+---------------+
| Control block |
|               |
+ ............. +
|  Object (T)   |
|               |
+---------------+

因此,即使您将引用传递给对象,make_shared也会创建自己的“深层”副本(在其中构建其对象副本)如上所述分配的存储块的一部分。)