当一个类有一个未定义其移动操作的成员时,我很难理解隐式移动操作:
int main() {
struct A // no move: move = copy
{
A() = default;
A(const A&) {
cout << "A'copy-ctor\n";
};
A& operator=(const A&) {
cout << "A'copy-assign\n";
return *this;
}
};
struct B
{
B() = default;
A a; // does this make B non-moveable?
unique_ptr<int> upi;
// B(B&&) noexcept = default;
// B& operator=(B&&)noexcept = default;
};
A a;
A a2 = std::move(a); // ok use copy ctor instead of move one
a2 = std::move(a); // ok use copy assignment instead of move one
B b;
B b2 = std::move(b); // why this works?
b = std::move(b2); // and this works?
// b = b2; // error: copy deleted because of non-copyable member upi
cout << "\nDone!\n";
}
所以我看到的A
是一个不可移动的类,因为它定义了复制控制操作,所以它只能被复制,并且任何试图移动这个类的对象,都会使用相应的复制操作。
如果我是正确的,直到这里它是好的。但是B
有一个不可复制的对象upi
,unique_ptr
因此复制操作被定义为已删除的函数,因此我们无法复制此类的对象。但是这个类有一个不可移动的对象a
,因此我认为这个类 ( B
) 既不能复制也不能移动。但是为什么初始化b2
和分配b
工作正常?究竟会发生什么?
B b2 = std::move(b); // ok?!
为什么上面的行调用了类的复制构造函数A
并且它调用了移动构造函数B
?
- 对我来说情况变得更糟:如果我取消注释中的移动操作行,
B
上面的初始化将不会编译抱怨引用已删除的函数,赋值也是如此!
谁能帮我到底发生了什么?在在这里发布问题之前,我已经在 cppreference 和许多网站上搜索并阅读过。
输出:
A'copy-ctor
A'copy-assign
A'copy-ctor
A'copy-assign
Done!