学习定位:现代 C++ 核心知识。右值引用是理解移动语义和 std::move 的前置概念;普通开发者先掌握基础值类别和“可被移动”的含义即可。

右值引用是 C++11 引入的一种新的引用类型,用 T&& 表示。它是实现移动语义和完美转发的基础。

1. 左值与右值

在理解右值引用前,必须分清左值和右值。

类别定义示例
左值(lvalue)有内存地址的表达式,可以取地址,通常出现在赋值左侧变量名、*ptr、数组元素、函数返回左值引用的调用
右值(rvalue)临时对象、字面量、即将被销毁的值,不能取地址42a+bstd::move(x)、函数返回非引用类型
int x = 42;   // x 是左值,42 是右值
int& ref = x; // 左值引用,只能绑定左值
// int& ref2 = 42;   // 错误,左值引用不能绑定右值
const int& cref = 42; // const 左值引用可以绑定右值(延长生命周期)

2. 右值引用语法

  • 右值引用用 && 声明,只能绑定右值。
  • 作用:标识一个对象是临时的、可被“窃取”资源的。
int&& rref = 42;      // 右值引用绑定到字面量(右值)
int x = 10;
// int&& rref2 = x;   // 错误,不能绑定左值
int&& rref3 = std::move(x); // std::move 将左值转为右值引用

3. 右值引用的特性

  • 延长临时对象生命周期(类似 const &,但可修改)
  • 区分移动语义:重载函数时,右值引用参数匹配临时对象
  • 用于移动构造函数/赋值:见移动语义笔记
void process(const int& x) { std::cout << "copy\n"; }
void process(int&& x)      { std::cout << "move\n"; }
 
int main() {
    int a = 5;
    process(a);    // 输出 copy(左值)
    process(10);   // 输出 move(右值)
    process(std::move(a)); // 输出 move
}

4. 右值引用与左值引用的区别

类型语法绑定对象可修改能否延长临时对象生命周期
左值引用T&只能左值
const 左值引用const T&左值或右值是(但只读)
右值引用T&&只能右值是(可修改)

5. 常见误区

  • 右值引用本身是左值:一旦右值引用变量有了名字,它在后续代码中就是一个左值。
int&& rref = 42;
int* p = &rref;      // 合法,rref 有地址,是左值
int&& rref2 = rref;  // 错误,rref 是左值,不能绑定到右值引用

这一特性解释了为什么移动构造函数中需要 std::move 来再次转为右值引用。


下一节 移动语义