移动构造函数在C++11后用于高效转移临时或显式标记为可移动对象的资源。典型触发场景包括:用右值初始化新对象、函数返回局部对象(未被RVO优化时)、容器插入临时对象或显式std::move、throw/catch中抛出支持移动的临时对象;不触发的情况有:直接构造临时对象、C++17起拷贝初始化强制省略、const左值引用传参、const左值加std::move后无匹配移动构造函数;std::move仅作类型转换,不执行移动操作,实际是否移动取决于是否存在可用的T&&重载;移动后源对象处于有效但未指定状态,可析构或赋值,但不可依赖其原值。

移动构造函数在C++11及以后版本中,当一个对象需要“接管”另一个临时或明确标记为可移动对象的资源(如动态内存、文件句柄等)时被调用,核心前提是:源对象不再需要其资源,且能安全地被“掏空”。
触发移动构造函数的典型场景
编译器会在以下情况自动选择移动构造函数(前提是该函数存在且未被删除,且不违反访问控制):
- 用一个右值(如临时对象、std::move包装的左值)初始化新对象:MyClass a(std::move(b)); 或 MyClass a(MyClass());
- 函数返回局部对象(满足RVO条件时可能被优化掉,但未优化时会触发移动):MyClass create() { return MyClass(); } → auto x = create();
- 向容器插入临时对象或使用std::vector::push_back(std::move(obj))等显式移动操作
- throw/catch中抛出临时对象,且异常对象类型支持移动(非const左值引用捕获除外)
移动构造函数不会被调用的常见误解
不是所有“看起来像移动”的操作都会调用它:
- 直接初始化临时对象本身(如MyClass())不调用移动,只调用普通构造函数
- 拷贝初始化写法MyClass a = MyClass();在C++17前可能触发移动(也可能被优化),C++17起强制省略拷贝/移动(guaranteed copy elision),不调用任何构造函数
- 传入const左值引用参数(如void f(const MyClass&))不会触发移动——它走的是const引用绑定,跟移动无关
- 源对象是const左值(如const MyClass x;),即使加std::move(x),也只会匹配const右值引用(如果定义了),否则退化为拷贝(因const T&&无法绑定非常量移动构造函数)
手动触发移动的关键:std::move的作用
std::move本身不移动任何东西,它只是一个强制类型转换工具,把左值转换为对应类型的右值引用(xvalue),从而让重载解析有机会选中移动构造函数或移动赋值运算符:
版权声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。
还木有评论哦,快来抢沙发吧~