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??
如果创建的对象没有名称,则称为 temporary 或 r-value 并且编译器有不同的规则r-values 比 named objects 或 l-values.
命名对象(l-值)只能复制到另一个对象,但未命名对象(r- values) 可以 copied 或 moved.
在您的示例中,您使用了 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!!!
然后编译器可以 copy 或 move 并且它总是尝试 move试图复制。
std::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);
}
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??
如果创建的对象没有名称,则称为 temporary 或 r-value 并且编译器有不同的规则r-values 比 named objects 或 l-values.
命名对象(l-值)只能复制到另一个对象,但未命名对象(r- values) 可以 copied 或 moved.
在您的示例中,您使用了 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!!!
然后编译器可以 copy 或 move 并且它总是尝试 move试图复制。
std::unique_ptr
完全移动投诉所以编译器没有投诉。