循环:for / while
更新时间:2026-08-27。本文是
languages/cpp/主题入门层第 9 篇。上一篇讲完分支,这一篇把循环补齐:for、while、do-while语法和 C 一样,但 C++11 的"范围 for"让遍历数组/容器成了最舒服的写法,值得单独拎出来说。
本文要回答的问题
- C++ 的
for/while和 C 有什么差别? - "范围 for"是什么,凭什么比下标遍历省心?
- 死循环、
break/continue有什么要注意的?
一、经典三兄弟:语法和 C 一致
// for:计数循环
for (int i = 0; i < 10; ++i) {
std::cout << i << "\n";
}
// while:条件循环
int n = 3;
while (n > 0) {
std::cout << n << "\n";
--n;
}
// do-while:先做一次再判断
int m;
do {
std::cout << "至少进来一次\n";
} while (false);三种写法和 C 逐字相同:for (初始化; 条件; 步进)、while (条件)、do ... while (条件)。注意 do-while 结尾的分号,别漏。C 里那些坑——忘记更新循环变量导致死循环、i++ 和 ++i 在循环里的细微差别——在 C++ 里一个都不少。
关于 i++ vs ++i:for (int i = 0; i < n; ++i) 里两者行为一样,性能差异在现代编译器下也可以忽略。但养成 ++i 的习惯没坏处——后面遇到迭代器、std::string 的 ++it 时,前置自增天然少一次临时拷贝,那是实打实的。
二、范围 for:C++11 最值得炫耀的遍历
数组遍历在 C 里是这么写的:
int arr[5] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; ++i) {
printf("%d\n", arr[i]);
}C++11 起有了"范围 for"(range-based for):
int arr[5] = {1, 2, 3, 4, 5};
for (int x : arr) {
std::cout << x << "\n";
}读作"对 arr 里的每个元素 x 做……"。不用写下标、不用算长度、不怕越界——std::vector、std::string、数组、std::map 这些容器全都一套写法:
std::string s = "hello";
for (char c : s) { // 字符串按字符遍历
std::cout << c << "-";
}三个变体要分清:
for (int x : arr) // 拷贝每个元素(只读、元素小、用这个)
for (int& x : arr) // 引用,能改原数组里的元素
for (const int& x : arr) // 常引用,只读不拷贝(元素大、用这个)第一个变体遍历 std::string 会逐个拷贝字符(没事,字符小);遍历 std::vector<SomeBigStruct> 就会拷贝整个结构体,这时候用 const auto&(auto 下一篇讲,先用着)省一大笔开销。想改元素就加 &,只读就 const &,这个肌肉记忆早点练起来。
三、死循环、break、continue
while (true) { // 死循环:服务器主循环、事件循环的标配
// ...
if (done) break; // break:跳出整个循环
}
for (int i = 0; i < 10; ++i) {
if (i % 2 == 0) continue; // continue:跳过本次,进下一次
std::cout << i << "\n"; // 只打印奇数
}break结束当前循环,continue跳过本次迭代的剩余部分;break只跳出一层循环——嵌套两层想全跳出,要么用标志变量,要么重构,别硬写多层的 goto;- 范围 for 里同样能用
break/continue,逻辑一致。
goto 在 C++ 里合法但名声不好,跳进/跳出作用域(尤其跳过对象构造)是禁止的,日常完全用不上它。
四、和 C 对比
| 对比项 | C | C++ |
|---|---|---|
for / while / do-while | 有 | 语法一致 |
| 数组遍历 | 下标 + 长度,手动防越界 | 范围 for,自动管理 |
| 容器遍历 | 没有标准容器(结构体数组手搓) | vector/string/map 通用范围 for |
| 修改元素 | arr[i] = x | for (auto& x : arr) |
break / continue | 有 | 一样 |
| 循环内声明变量 | C99 起允许 | 一直允许,且作用域限制在循环内 |
有个细节值得说:C 里 for (int i = 0; ...) 从 C99 才合法,而 C++ 从第一天起就是这样,并且 i 的作用域被严格限制在循环体内——循环结束 i 就没了,想在外面用必须提前声明。这能避免一类"循环变量泄漏"的脏问题。
五、与本站主线衔接
- 循环是 CPU 性能剖析的绝对主战场:热点循环、循环展开、向量化,见 L4 微架构与优化 与
perf剖析工具; - 本站演示程序
demos/cpu-demo的核心就是for循环跑出 CPU 热点,make release时-O2直接把它优化掉,是"循环与优化器"最直观的活教材; - 内存布局对遍历性能的影响(连续数组 vs 链表),见 L3 缓存与局部性;
- C 的循环对照与更多细节,见 C for 循环 与 C while 循环。
一句话总结
for / while / do-while 沿袭 C 语法,但 C++11 的范围 for 让遍历数组和容器只需要"对每个元素"一句话;想改元素加 &、只读用 const &、元素小才用值拷贝;break / continue 规则不变,嵌套跳出靠标志变量别靠 goto。
上一篇:if / switch 分支 下一篇:auto 与类型推导