移动语义的核心是资源移交而非复制,需正确声明noexcept移动操作、识别隐式移动时机、慎用std::move,并确保移动前提(如禁用或默认拷贝操作)到位。
移动语义的核心目标,是用“搬走资源”代替“复制资源”,从而避免深拷贝开销。关键不在于写几个 std::move,而在于识别可移动的右值、正确声明移动构造函数/移动赋值运算符,并让编译器有机会自动调用它们。
编译器在特定场景下会自动选择移动而非拷贝,前提是类提供了合规的移动操作:
return std::string("hello");)——触发返回值优化(RVO)或自动移动(C++17起 guaranteed copy elision + move fallback)std::vector v = get_temp_vector(); )——若 get_temp_vector() 返回右值,且 vector 有移动构造函数,则调用移动而非拷贝构造vec.push_back(std::string("tmp"));)——push_back 的右值重载会调用移动构造移动构造函数和移动赋值运算符不是“更快的拷贝”,而是“资源移交协议”:
noexcept:否则标准容器(如 std::vector 在扩容时)可能拒绝使用移动,退回到拷贝obj = std::move(obj); 合法),通常用“先移后清”或交换惯用法(swap(*this, other);)std::move(x) 只是把 x 强转为右值引用,不执行任何移动动作。滥用会导致意外移动或重复移动:
std::move 后,该变量不再可
用——后续访问是未定义行为T&&)无条件调用 std::move:万一是从左值传入的转发引用(universal reference),应优先用 std::forward
即使写了移动操作,如果类还存在用户定义的拷贝构造函数或拷贝赋值运算符,编译器不会自动生成移动操作(C++11/14)。必须显式声明或 = default:
const T& 构造),且未提供移动操作,编译器只用拷贝——性能白丢std::unique_ptr),需显式 = delete 拷贝操作,并 = default 移动操作= default,也可能被隐式声明为 defaulted;但仍建议显式写出以明确意图