在 C++ 的世界里,表达式的结果有着不同的'存在方式'。有的值可以反复引用和修改,比如一个变量;有的值只是临时存在的计算结果,比如 a + b。为了区分它们,C++ 把表达式结果分为两类:左值(lvalue)和右值(rvalue)。这两个概念几乎贯穿了整个语言体系,也是理解'引用'、'移动语义'、'完美转发'的基础。
为什么要区分左值与右值?
在 C++ 中,表达式的结果(一个值)有不同的'存在方式'。有的值是可以被再次引用和修改的(比如一个变量),有的值只是临时存在的计算结果(比如 a + b)。
为了区分它们,C++ 把表达式结果分为两类:
- 左值(lvalue)
- 右值(rvalue)
这两个概念几乎贯穿了整个语言体系,也是理解'引用'、'移动语义'、'完美转发'的基础。
左值(Lvalue)是什么?
定义
左值(locator value)表示在内存中有确定地址、可以被取地址(&)的对象。换句话说,左值是有名字、能被赋值的东西。
示例
int x = 10; // x 是左值
x = 20; // ✅ 左值可以出现在赋值号左边
int* p = &x; // ✅ 可以取地址
在这里,x 是一个左值,因为:
- 它有名字;
- 它在内存中有一块固定的存储空间;
- 它的生命周期由程序控制。
右值(Rvalue)是什么?
定义
右值是没有明确内存地址的临时对象或字面值。它通常出现在赋值号的右侧,用来给左值赋值。
示例
int y = x + 5; // x + 5 是右值(表达式结果)
y = 10; // 10 是右值(字面量)
右值的特征:
- 通常不能取地址;
- 生命周期很短(表达式结束即销毁);
- 用完即弃。
引用的两种类型
C++ 引用(reference)是变量的'别名',但 C++11 之后区分了两类:
- 左值引用:绑定到左值,允许修改原对象。
- 右值引用:绑定到右值,用于转移资源。
右值引用的引入:C++11 的革命
右值引用(&&)是 C++11 引入的一个关键特性。它的出现是为了解决临时对象被频繁复制导致性能浪费的问题。
示例:
std::string a = "Hello";
std::string b = a; // 拷贝构造,复制内存
std::string c = std::(a);


