编辑:我理解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);
}
答案 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 < em>比命名对象或 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));
编译