引自 C ++ Primer
如果我们明确要求编译器生成移动操作 使用
= default
,编译器无法移动所有 成员,然后移动操作将被定义为已删除移动构造函数定义为已删除如果 class有一个定义自己的复制构造函数的成员,但也没有 定义移动构造函数,或者如果类具有未定义它的成员 自己的复制操作,编译器无法合成移动 构造
有些代码似乎违反了这条规则:
#include <utility>
#include <iostream>
struct X {
X() = default;
X(const X&) { std::cout << "X(const X&)" << std::endl; }
int i;
};
struct hasX {
hasX() = default;
hasX(const hasX &) = delete;
hasX(hasX &&) = default;
X mem;
};
int main()
{
hasX hx, hx2 = std::move(hx); //output is X(const X&)
}
X
没有定义移动构造函数,编译器也无法合成它。
根据上述规则,hasX
的移动构造函数将被删除。
但是,由于hasX
的复制构造函数已被删除,hx2 = std::move(hx)
必须调用移动构造函数来输出"X(const X&)"
,其中显示hasX
&#39; s定义了移动构造函数,并使用X
的复制构造函数来移动&#34;移动&#34;。这似乎违反了上述规则。
那么,是在C ++标准中定义还是仅仅是编译器实现?
我测试的编译器:VS2015和a online compiler
谢谢你的帮助!
答案 0 :(得分:3)
你的书似乎错了。 Copying is a valid move operation因此,只要该成员具有const type&
形式的复制构造函数,因此它可以绑定到rvalues,移动操作将回退到副本。
在你的例子中
hasX(hasX &&) = default;
可以替换为
hasX(hasX &&rhs) : mem(std::move(rhs.mem)) {}
因为这是默认的,它会编译得很好。