C++学习笔记 | C++ 的"偷懒"规则:短路运算,坑了很多同学
- 2026-11-06 15:16:27

一、先看一道题,你能说出答案吗?
前几天梁爸接到同学发来的一段代码,同学有疑问,说代码算不对:
#include <bits/stdc++.h>using namespace std;int main(){ int a = 1, b = 2; if (a > 0 || b++ > 0) cout << b;}这段代码确实坑了不少同学,现在请你先别急着看下面内容,自己在心里回答两个问题:
1. 屏幕上会输出什么数字? 2. 算完之后,b 变成了几?
我猜很多同学是这么想的:
b++嘛,b从 2 变成 3;b++ > 0就是2 > 0,对的;a > 0也是对的;所以条件成立,输出b,那就是 3。
如果你的答案是 3,恭喜你——掉进坑里了。😄
正确答案是:
2b从头到尾都是 2,那个 b++压根就没有执行过!
为什么会这样?这就是今天要讲的:短路运算。
二、什么是"短路"?
"短路"这个词,我们在物理的电路里听过,很多同学还知道电路短路会“冒烟”,烧坏电器,但怎么C++里也有短路,别着急,我们来一起看:
C++ 里的短路的意思:后面的内容不走了。
我们来认识两位主角:
它们用起来很简单:
if (肚子饿 && 有零食) cout << "开吃!";if (下雨 || 太晒) cout << "带伞!";关键在于:电脑在判断这两个符号时,特别爱"偷懒"。
偷懒规则表(超级重要,建议抄下来)
A && B | A 是假的时候 | |
A || B | A 是真的时候 |
用同学们能看懂的语言翻译一下这个重要原理:
&&(并且):&&在逻辑运算中是“逻辑乘”(×),左边是"假"(0),乘法运算后整个条件就一定是假(0),这样右边是什么就没必要看了。
||(或者):||在逻辑运算中是“逻辑加”(+),只要左边是"真"(1),加法运算后整个条件就一定是真(1),右边是什么就没必要看了。
就像妈妈让你去超市:
• &&版本:"带牛奶并且带面包回来。"→ 到货架前一看,牛奶卖完了(假)。那还买面包干嘛?直接回家!(右边不执行,短路了)• ||版本:"带牛奶或者带面包回来,带一样就行。"→ 进超市看有牛奶。任务已完成,面包不用拿了!(右边不执行,同样短路了)
三、回到开头那道题
现在用短路规则重新看一遍:
int a = 1, b = 2;if (a > 0 || b++ > 0) cout << b;第一步:电脑先看 || 的左边 ——a > 0
a 是 1,1 > 0 是真。
第二步:因为是 ||,左边已经是真了,整个条件必定成立,右边不用看,直接短路!
于是
b++ > 0这一段被整段跳过,b++一次都没执行。
第三步:条件成立,执行 cout << b。
此时 b还是原来的2。
所以屏幕输出2,而不是 3。
一句话总结:
b++被"跳过"了,所以b没机会变大。
四、换成 && 试试,答案立刻不一样
把上题的 || 换成 &&:
int a = 1, b = 2;if (a > 0 && b++ > 0) cout << b;这次结果是 3!
为什么? 因为 && 的偷懒条件是"左边为假",而这里 a > 0 是真——左边是真,就不能偷懒,必须继续算右边。
于是 b++ > 0 正常执行:先拿 2 去比较(成立),再把 b 变成 3。
最后输出 3。
同一个 b++,一个被跳过、一个正常执行,答案就差 1。 这就是短路运算最容易咬人的地方。
五、四个小实验,自己动手验证
光看容易忘,建议把这四行分别跑一跑,感受一下区别。
// 实验一:|| 左边为真 → 右边跳过int b = 2;if (1 > 0 || b++ > 0) {} // b++ 被跳过cout << b << endl; // 输出 2// 实验二:|| 左边为假 → 右边执行int b = 2;if (1 < 0 || b++ > 0) {} // b++ 执行了cout << b << endl; // 输出 3// 实验三:&& 左边为假 → 右边跳过int b = 2;if (1 < 0 && b++ > 0) {} // b++ 被跳过cout << b << endl; // 输出 2// 实验四:&& 左边为真 → 右边执行int b = 2;if (1 > 0 && b++ > 0) {} // b++ 执行了cout << b << endl; // 输出 3把这张表记住,基本就不会错了:
b | |||
|---|---|---|---|
1>0 || b++>0 | |||
1<0 || b++>0 | |||
1<0 && b++>0 | |||
1>0 && b++>0 |
读法提示:
||看到"真"就偷懒,&&看到"假"就偷懒。两个符号的偷懒条件刚好相反!
六、顺带搞懂:b++和++b 差在哪
短路题里经常混着 ++,这里一并讲清楚。
b++ 和 ++b 都会让 b 加 1,区别在于"返回值"是什么。
int b = 2;int r = b++;// 此时 r = 2,因为先把原来的 2 给了 r,b 才变成 3int b = 2;int r = ++b;// 此时 r = 3,因为先让 b 变成 3,再把 3 给 r用一句话记住:
b++是"先交货,后加工";++b是"先加工,后交货"。
在开头那道题里,b++ > 0 是拿原来的 2 去和 0 比较的。
不过要注意:如果整段被短路跳过了,b++ 连"交货"的机会都没有,b 根本不会变。 这就是问题的核心。
七、短路运算有什么好处?
看到这里你可能会想:这规则这么坑,干脆别用它算了?
恰恰相反,短路运算是个好东西,它有两个大用处:
用处一:省时间,让程序更快
if (arr.size() > 0 && arr[0] == 100) { ... }这句的意思是:先确认数组不是空的,再去取第 0 个元素。
如果数组真的是空的,arr.size() > 0 是假,&& 直接偷懒,后面 arr[0] 就不去碰了——避免了一次出错。
得益于短路,程序跑起来又快又安全。要是没有短路,电脑会傻乎乎地去取一个不存在的元素,程序可能直接崩掉。
用处二:用来做"安全检查"
if (p != NULL && p->value > 0) { ... }先判断指针不是空的,再去读它的内容。顺序很重要,靠的就是短路规则在背后保护我们。
八、写代码时的三条重要建议
既然短路的"跳过"是合法的,那就别在右边放"必须要执行"的操作。
建议一:别把 ++ 塞进条件里
// ❌ 不推荐:b 涨不涨,取决于左边,很难一眼看出if (a > 0 || b++ > 0) { ... }// ✅ 推荐:分开写,清清楚楚bool flag = (a > 0) || (b > 0);b++;建议二:需要右边一定执行时,别用 && / ||
// ❌ b++ 可能不执行if (a > 0 || b++ > 0) { ... }// ✅ 用 & 或 |(不短路,两边都会算)if ((a > 0) | (b++ > 0)) { ... }注意:
&和|是单个符号,它们不短路,两边都会老老实实算完。这一点和&&、||完全不同,别记混了。不过平时写代码,还是推荐用上面"建议一"的写法,最清楚。
建议三:把"必须做的动作"从条件里挪出来
// 判归判,做事归做事if (a > 0 || b > 0) { b++; // 放在花括号里,一定会执行 cout << b << endl;}九、总结
把今天的三件事记住,就能避开这个坑:
1. &&看到左边是"假"就偷懒——右边不执行。2. ||看到左边是"真"就偷懒——右边不执行。3. 被跳过的 b++,不会让b变大。
再回头看开头那道题:
int a = 1, b = 2;if (a > 0 || b++ > 0) cout << b; // 输出 2a > 0 是真 → || 偷懒 → b++ 被跳过 → b 还是 2 → 输出 2。
下次再遇到"看着像 3、其实是 2"的题,你就知道该往哪儿找了。
十、一起做两道题练手
第 1 题
int a = 0, b = 5;if (a > 0 || b++ > 3) cout << b;输出是多少?b 最后是几?
第 2 题
int x = 3, y = 10;if (x < 0 && y++ > 5) cout << y;cout << y;输出是多少?
第 1 题:输出 6。a > 0 是假(a 是 0)→ || 不能偷懒,右边要执行 → b++ > 3 拿 5 比较成立,b 变成 6 → 输出 6。
第 2 题:输出 10。x < 0 是假 → && 偷懒,y++ 被跳过 → y 保持 10 → if 条件不成立,不执行内部语句 → 最后单独输出 y,得到 10。
思考题:前面说过 | 和 & 不短路。如果开头那道题写成 if (a > 0 | b++ > 0),结果会变成几?动手试试看!
如果内容对您有帮助,
欢迎关注、转发,点赞!!!
您的鼓励是我们最宝贵的动力!!
欢迎添加梁爸的微信
欢迎关注乐源素质公众号

