unique_ptr 在成员初始化列表中

unique_ptr in member initialization list

编辑: 我知道 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); 
}
MyObject() : ptr(std::unique_ptr<int>(new int))

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

您可以将 main 更改为

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

编译

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

第二次(在main中),std::unique_ptr<int> ptr2(ptr)不行,因为ptr是左值,不能直接移动(可以用std::move ).

这与已命名未命名 对象有关。

当你这样做时:

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

但是当你这样做时:

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

如果创建的对象没有名称,则称为 temporaryr-value 并且编译器有不同的规则r-valuesnamed objectsl-values.

命名对象(l-值)只能复制到另一个对象,但未命名对象(r- values) 可以 copiedmoved.

在您的示例中,您使用了 std::unique_ptr。这些对象只能 moved 因为它们的复制语义已被禁用。这就是当您尝试 copy one:

时编译器出错的原因
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 并且它总是尝试 move试图复制

std::unique_ptr完全移动投诉所以编译器没有投诉。