成员初始化列表中的unique_ptr

unique_ptr in member initialization list

本文关键字:unique ptr 初始化 列表 成员      更新时间:2023-10-16

编辑:我知道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); 
}

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

当你这样做时:

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

但当你这样做时:

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

如果创建的对象没有名称,则称为临时r值,并且编译器对r值的规则与对命名对象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!!!

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

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

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

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

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

其使用CCD_ 10的移动构造函数(来自临时(。

您可以将main更改为

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

编译