成员初始化列表中的unique_ptr

pep*_*ero 8 c++ constructor initialization unique-ptr c++11

编辑:我理解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); 
}
Run Code Online (Sandbox Code Playgroud)

Nel*_*eal 9

在你的例子中,std::unique_ptr<int>(new int)是一个rvalue,所以使用了move-constructor ptr.

第二次(in main),std::unique_ptr<int> ptr2(ptr)因为ptr是左值而不起作用,并且不能直接移动(你可以使用std::move).


Gal*_*lik 8

这与命名未命名对象有关.

当你这样做:

std::unique_ptr<int> ptr(new int);
                     ^^^--- name is 'ptr'
Run Code Online (Sandbox Code Playgroud)

但是当你这样做时:

std::unique_ptr<int>(new int);
                    ^--where is the name??
Run Code Online (Sandbox Code Playgroud)

如果创建的对象没有名称,则称为临时r值,并且编译器对r值的规则与对命名对象l值的规则不同.

命名对象(l值)只能复制到另一个对象,但可以复制移动未命名的对象(r值).

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

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

ptr是一个命名对象,因此只能复制它,但它的复制语义被禁用,因此整个操作是非法的.

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

MyObject() : ptr(std::unique_ptr<int>(new int)) 
                                     ^--- look no name!!!
Run Code Online (Sandbox Code Playgroud)

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

std::unique_ptr完全移动的投诉,因此编译器没有怨言.