成员初始化列表中的unique_ptr

时间:2016-08-16 21:58:02

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

编辑:我理解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); 
}

3 个答案:

答案 0 :(得分:7)

在您的示例中,std::unique_ptr<int>(new int)是一个右值,因此使用了ptr的move-constructor。

第二次(main),std::unique_ptr<int> ptr2(ptr)无法正常工作,因为ptr是左值,无法直接移动(您可以使用std::move )。

答案 1 :(得分:5)

这与名为未命名的对象有关。

执行此操作时:

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

但是当你这样做时:

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

如果创建的对象没有名称,则称为临时 r-value ,编译器对 r-values 命名对象 l-values

命名对象( l-values )只能复制到另一个对象,但未命名的对象( r-values )可以< em>已复制已移动

在您的示例中,您使用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!!!

然后编译器可以复制移动,并且在尝试复制之前总是尝试移动

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

答案 2 :(得分:1)

MyObject() : ptr(std::unique_ptr<int>(new int))

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

您可以将main更改为

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

编译