未声明移动构造函数调用拷贝构造,显式删除则编译错误的原因
C++移动构造函数的行为差异解析
问题场景
代码示例1
#include <iostream> using namespace std; struct X { X() = default; X(const X& src) { cout << "copy" << endl; } }; int main() { X x1; X x2(move(x1)); }
输出结果:
copy
代码示例2
#include <iostream> using namespace std; 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)); | ^
核心困惑
未声明移动构造函数时,编译器未生成默认版本,转而调用了拷贝构造函数;但显式删除移动构造函数后,却直接触发编译错误,这两种行为的差异是什么原因导致的?
原因解析
默认移动构造函数的生成规则
C++标准明确规定:当类显式声明了拷贝构造函数、拷贝赋值运算符、析构函数中的任意一个时,编译器不会自动生成默认移动构造函数。第一个示例中,因为已经定义了拷贝构造函数,编译器不会生成移动构造函数。此时move(x1)将x1转换为右值引用,但由于没有匹配的移动构造函数,编译器会尝试寻找兼容的构造函数——拷贝构造函数的const X&参数可以绑定到右值(const左值引用的特性),因此最终调用拷贝构造函数,程序正常运行。显式删除移动构造函数的影响
当你显式声明X(X&&) = delete;时,这个移动构造函数会被加入类的重载候选集。执行X x2(move(x1));时,编译器会优先匹配参数类型完全吻合的构造函数——也就是被删除的移动构造函数。在重载匹配规则中,右值引用参数比const X&更匹配右值,因此编译器不会降级去调用拷贝构造函数。由于匹配到了一个被删除的函数,直接触发编译错误。
内容的提问来源于stack exchange,提问作者Andrey Rubliov
相关产品推荐
相关产品推荐

