📄 一句话概括
左值(lvalue)= 有地址的"盒子",能放在 = 左边;右值(rvalue)= 临时算出来的"气球",只能读、飘在半空。判断口诀就一句:能被赋值 / 能取地址的,是左值。2 = a 为什么报错?本节给出终审裁决。
一、两个概念,一个比方
| 左值 lvalue | 右值 rvalue | |
|---|---|---|
| 本质 | 占着内存的盒子 | 临时算出的值 |
| 有没有地址 | 有(能取地址) | 没有(算完就散) |
| 能不能被赋值 | 能 | 不能 |
| 出现位置 | = 两边都行 |
只能 = 右边 |
| 比方 | 贴了门牌号的仓库 | 气球(没地方贴门牌) |
int a = 5;
a // 左值:变量是盒子
5 // 右值:字面量是气球
a + 1 // 右值:算式结果是新气球(即使 a 是盒子)
a = 10 // 整个赋值表达式的值(10)也是右值
注意最容易被忽略的一条:a + 1 虽然含有盒子 a,但算出来的结果是个新值——临时气球。所以 a + 1 = 5 报错,哪怕表达式里有变量。
二、终审裁决台:= 的左边必须是左值
编译器看到 =,第一件事就是检查左边:
a = 5; // 过:a 是盒子
5 = a; // 不过:气球上没地方写字
a + 1 = 5; // 不过:算式结果是气球
a = b + 1; // 过:左边是盒子,右边随便是啥
这就是 3.1.4 "左边必须是个盒子"的原理层:赋值的本质是"把值写进一块有地址的内存"——气球没有地址,写不进去。
术语解密:lvalue = location value(有位置/地址的值)——"左值"这个名字只是因为常在左边,本质是"有地址"。右值同理是"只能读的临时值"。
三、简单裁决法
拿到一个东西,两步判型:
- 它是变量名吗? → 大概率左值
- 它是字面量、算式结果、比较结果、函数返回值吗? → 右值
几个边界案例练手感:
| 表达式 | 判定 | 理由 |
|---|---|---|
x |
左值 | 变量盒子 |
3.14 |
右值 | 字面量 |
x + 1 |
右值 | 临时结果 |
x *= 2 |
右值 | 赋值表达式的"值"是临时的 |
"hello" |
右值 | 字符串字面量 |
为什么这门课要学它? 一是看懂报错(error: lvalue required as left operand of assignment 是新手高频错误,报错名里就有 lvalue);二是第 8 章函数返回值、将来 C++11 的移动语义都要靠这组地基——现在把"盒子 vs 气球"的直觉立起来。
四、动手 Demo:裁决台现场
#include <iostream>
using namespace std;
int main() {
int a = 1, b = 2;
a = 5; // 过
a = b + 1; // 过
// 5 = a; // 取消注释:报错 lvalue required
// a + 1 = 5; // 取消注释:报错 lvalue required
// 进阶冷知识(能编过,知道即可):C++ 里赋值表达式本身的结果是左值,
// 所以 (a = b) = 9; 合法且 a 变 9——这条和 C 语言不同,别深究,体会"赋值有值"的极端形态
cout << &a << endl; // 取地址成功 → 左值铁证(& 是第 8 章主角,先见识)
return 0;
}
动手方式:逐条取消注释编译,把报错原文抄进笔记——lvalue required 这个报错你这一生还会见很多次,第一次见就要认得。
30 秒实验:&a 输出一个十六进制地址(如 0x61ff08)——左值有地址的直接证据;再试 &(a + 1)——编译报错,气球取不了地址。
五、常见误区
- "左值就是'在左边的值'"——名字的由来,不是定义。本质是有地址。
a = b里 b 在右边,但它仍是左值。 - "表达式里有变量,就是左值"——
a + 1含盒子但结果是气球。看整体表达式的结果,不看零件。 - "常量变量 const 不能赋值,所以不是左值"——const 变量仍是左值(有地址),只是"不许写"。左值分可写和只读两种。
- "这概念考试才用"——
lvalue required报错、第 8 章函数返回值、C++11 移动语义全在这地基上。现在立直觉,将来省大力。
自测四问(点开对答案)
1. `x = 3` 中,x、3、整个表达式分别是什么?——x 左值、3 右值、整个赋值表达式的值(3)是右值。 2. `a + 1 = 5` 为什么错?——算式结果是临时值(气球),无地址可写,不能当 = 左边。 3. 判断左值的口诀?——能被赋值/能取地址的,是左值。 4. `2 = a` 的报错里会看到哪个词?——`lvalue`(lvalue required as left operand of assignment)。- ☐ 3.5 小结(下一节)