struct X
{
X() = default;
X(const X& src)
{
cout << "copy" << endl;
}
};
int main()
{
X x1;
X x2(move(x1));
}
输出: 复制
struct X
{
X() = default;
X(const X& src)
{
cout << "copy" << endl;
}
X(X&& src) = delete;
};
int main()
{
X x1;
X x2(move(x1));
}
编译错误:
error: use of deleted function ‘X::X(X&&)’
28 | X x2(move(x1));
| ^
所以我很困惑。当我没有编写移动构造函数时 - 看起来它没有生成移动构造函数,因为它调用了我的复制构造函数。但是为什么当我显式删除第一个动作时却报错呢?
将重载定义为
delete
not 意味着“此重载不存在”。这意味着“这个重载存在,但尝试调用它是一个错误。”
int foo(double) { return 1; }
// there is no foo(int) at all
int const x = foo(int(5)); // compiles fine: chooses foo(double) overload
int bar(double) { return 2; }
int bar(int) = delete;
int const y = bar(int(5)); // error! chose bar(int) over bar(double) but bar(int) = delete
如果您没有在类中声明移动构造函数,但声明/定义了复制构造函数,那么您所写的正是您得到的。你的第一个
X
的构造函数有两个重载 X::X()
和 X::(X const&)
,就是这样。然后,您可以使用 X
xvalue(即引用现有对象的右值)来调用它。右值(包括 xvalues)can 绑定到 const&
引用,因此在 X::(X const&)
中选择 main
重载,并且您的代码可以正常编译。
如果您添加
X::X(X&&) = delete;
,那么您所写的就是您得到的。 X
现在有一个移动构造函数(声明了重载 X::(X&&)
),但调用它是一个错误。右值 更喜欢绑定到 &&
引用而不是
const&
引用,因此
main
现在尝试调用
X::X(X&&)
而不是
X::X(const X&)
并且失败。(有时候,你写的并不是你得到的。最重要的是,如果你既不写复制构造函数,也不写移动构造函数,也不写赋值函数,也不写析构函数,那么编译器会声明所有 5 个。这启用了零规则:更喜欢写根本不需要自定义特殊函数的类,其中编译器生成的函数已经是正确的。)