当类有一个未定义移动操作的成员时,我很难理解隐式移动操作:
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!
请记住在 C++ 中“移动”数据意味着什么(假设我们遵循通常的约定)。如果你移动物体x
反对y
, then y
接收其中的所有数据x
and x
是...好吧,我们不在乎什么x
只要它仍然有效即可销毁。很多时候我们会想到x
丢失所有数据,但这不是必需的。所需要的只是x
已验证。如果x
最终得到相同的数据y
,我们不在乎。
Copying x
to y
causes y
接收其中的所有数据x
, and x
保持有效状态(假设复制操作遵循约定并且没有错误)。因此,复制算作移动。除了复制操作之外还定义移动操作的原因不是为了允许新的东西,而是为了在某些情况下允许更高的效率。任何可复制的内容都可以移动,除非您采取措施阻止移动。
所以我看到的是A
是一个不可移动的类,因为它定义了复制控制操作,因此它只能被复制,并且任何试图移动此类对象的操作都会使用相应的复制操作。
我看到的是A
is a moveable类(尽管缺少移动构造函数和移动赋值),因为它定义了复制控制操作。任何移动此类对象的尝试都将依赖于相应的复制操作。如果您希望一个类可复制但不可移动,则需要删除移动操作,同时保留复制操作。(尝试一下。添加A(A&&) = delete;
按照你的定义A
.)
The B
类有一个可以移动或复制的成员,以及一个可以移动但不能复制的成员。所以B
本身可以移动但不能复制。什么时候B
被移动,则unique_ptr
成员将按照您的预期移动,并且A
成员将被复制(移动类型对象的后备A
).
事情对我来说变得更糟:如果我取消注释移动操作行B
,上面的初始化不会编译并抱怨引用已删除的函数,对于赋值也是如此!
更仔细地阅读错误消息。当我复制此结果时,“使用已删除函数”错误后面跟着一条提供更多详细信息的注释:移动构造函数已被删除,因为“其异常规范与隐式异常规范不匹配”。删除noexcept
关键字允许代码编译(使用 gcc 9.2 和 6.1)。
或者,您可以添加noexcept
到复制构造函数和复制赋值A
(保持noexcept
的移动操作B
)。这是演示默认移动操作的一种方法B
使用复制操作A
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)