【问题标题】:unique_ptr in member initialization list成员初始化列表中的 unique_ptr
【发布时间】:2016-08-16 21:58:02
【问题描述】:

编辑: 我知道 unique_ptr 是不可复制的,只能移动。我不明白初始化列表会发生什么。

为什么成员初始化列表中的 unique_ptr 可以像代码片段一样工作?

#include <memory>

class MyObject
{
public:
    MyObject() : ptr(new int) // this works.
    MyObject() : ptr(std::unique_ptr<int>(new int)) 
    // i found this in many examples. but why this also work? 
    // i think this is using copy constructor as the bottom.        
    {
    }

    MyObject(MyObject&& other) : ptr(std::move(other.ptr))
    {
    }

    MyObject& operator=(MyObject&& other)
    {
        ptr = std::move(other.ptr);
        return *this;
    }

private:
    std::unique_ptr<int> ptr;
};

int main() {
    MyObject o;
    std::unique_ptr<int> ptr (new int);
    // compile error, of course, since copy constructor is not allowed. 
    // but what is happening with member initialization list in above?
    std::unique_ptr<int> ptr2(ptr); 
}

【问题讨论】:

    标签: c++ c++11 constructor initialization unique-ptr


    【解决方案1】:

    在您的示例中,std::unique_ptr&lt;int&gt;(new int) 是一个右值,因此使用了 ptr 的移动构造函数。

    第二次(在main中),std::unique_ptr&lt;int&gt; ptr2(ptr)不起作用,因为ptr是左值,不能直接移动(可以使用std::move)。

    【讨论】:

      【解决方案2】:

      这与 namedunnamed 对象有关。

      当你这样做时:

      std::unique_ptr<int> ptr(new int);
      //                   ^^^--- name is 'ptr'
      

      但是当你这样做时:

      std::unique_ptr<int>(new int);
      //                  ^--where is the name??
      

      如果创建的对象没有名称,它被称为 temporaryr-value,编译器对 r-values 有不同的规则 em> 而不是 命名对象l-values

      命名对象(l-values)只能复制到另一个对象,但未命名对象(r-values)可以是复制或移动

      在您的示例中,您使用std::unique_ptr。这些对象只能移动,因为它们的复制语义已被禁用。这就是为什么当您尝试复制一个时您的编译器会出错:

      std::unique_ptr<int> ptr (new int);
      // compile error, copy constructor delete
      std::unique_ptr<int> ptr2(ptr); // copy is disabled!!
      

      这里ptr 是一个命名对象,所以它只能被复制,但是它的复制语义被禁用了,所以整个操作是非法的.

      但是当你对一个未命名的对象做类似的事情时:

      MyObject() : ptr(std::unique_ptr<int>(new int)) 
                                           ^--- look no name!!!
      

      然后编译器可以 copymove 并且它总是在尝试 copy 之前尝试 move

      std::unique_ptr 完全是移动投诉,因此编译器没有投诉。

      【讨论】:

      • 我不能接受两个答案。我从 Nelxost 中选择了一个,因为它更简洁
      【解决方案3】:
      MyObject() : ptr(std::unique_ptr<int>(new int))
      

      使用 std::unique_ptr 的移动构造函数(来自临时)。

      您可以将main 更改为

      std::unique_ptr<int> ptr2(std::move(ptr));
      

      编译

      【讨论】:

      • 当然,这只是一个好主意,如果 OP 真的想要 移动 指针,而不是说,有两个智能指针指向正确修复非常好的对象不同。
      • @Hurkyl:确实,如果 OP 想要共享所有权,应该使用 std::shared_ptr 而不是 std::unique_ptr,并保留副本。
      猜你喜欢
      • 2020-09-15
      • 1970-01-01
      • 2011-07-14
      • 2015-09-25
      • 2015-04-27
      • 2015-02-07
      • 2019-09-10
      • 2015-02-28
      • 2011-12-01
      相关资源
      最近更新 更多