右值引用和移动语义是C++11核心特性,通过绑定临时对象、转移资源指针避免深拷贝,显著提升vector等大对象性能;需手动实现移动构造/赋值函数,参数为T&&,内部用std::move转移成员,原对象置空后仅可析构或赋值。

右值引用和移动语义是 C++11 引入的核心特性,它们让程序能避免不必要的深拷贝,把临时对象的资源“偷过来”直接复用,显著提升性能——尤其在处理大对象(如 vector、string、自定义容器)时效果明显。
右值引用:绑定到临时对象的引用类型
右值引用用 && 表示,只能绑定到即将销毁的表达式(如字面量、函数返回的临时对象、std::move 转换后的对象),不能绑定到具名变量(左值)。它本身是个左值,但标记了“可被移动”的意图。
例如:
string s1 = "hello";string s2 = std::move(s1); // s1 被显式转为右值引用,触发移动构造
移动构造函数和移动赋值运算符:实现资源转移的关键
编译器不会自动生成移动函数(除非类没有自定义析构/拷贝/赋值,且所有成员都可移动)。你需要手动定义,把源对象的内部指针(如 char*、int*、vector::data())直接接管,再将源对象的指针置为 nullptr,防止析构时重复释放。
立即学习“C++免费学习笔记(深入)”;
典型写法要点:
- 参数类型必须是 T&&
- 内部用 std::move() 转移成员(如
data_ = std::move(other.data_)) - 原对象进入有效但未定义状态(比如指针为空),后续仅可安全析构或赋值
- 移动后不应再访问被移动的资源,否则行为未定义
移动语义如何提升性能?看一个真实场景
假设函数返回一个局部 vector:
vectorvector
return v; // 此处不调用拷贝构造,而是触发移动构造(C++17 后 guaranteed copy elision 更进一步)
}
如果没有移动语义,return 会触发一次深拷贝(分配新内存 + 逐个复制元素),耗时且占内存;有了移动语义,只是交换两个 vector 的内部指针和大小信息,开销接近 O(1)。
什么时候会自动触发移动?哪些情况不会?
编译器在满足条件时会隐式调用移动函数,常见于:
- return 局部对象(且类型匹配)
- throw / catch 临时对象
- 初始化列表中传入临时对象(如
vector)v{string("a"), string("b")}
但以下情况不会自动移动:
- 具名变量(即使是临时创建的)默认是左值,需用 std::move() 显式转换
- 函数返回值被绑定到 const T&(会延长生命周期,但阻止移动)
- 移动函数被删除(= delete)、不可访问,或未定义










