循环结构
建议先阅读:07_条件语句
原理
循环的 CPU 视角
循环在底层由三部分组成:
- 循环计数器:存储在寄存器中
- 条件判断:cmp + 条件跳转(循环体 vs 退出)
- 循环体:重复执行的指令块
编译器对循环的优化手段:
- 循环展开(loop unrolling):复制循环体减少分支判断次数
- 循环向量化(SIMD):用 SSE/AVX 指令一次处理多个元素
- 循环交换:调整嵌套循环顺序以优化缓存命中率
- 循环合并/分裂:合并相同范围循环或拆分多功能循环
循环变量作用域与栈帧
for (int i = 0; ...) 中 i 的作用域仅限于循环体内。循环体每次迭代不创建新的栈帧(与递归不同)——循环是单栈帧内的跳转,空间复杂度为 O(1)。递归每次调用创建新栈帧,空间复杂度为 O(n)。
range-based for 的实现
for (auto& x : arr) 被编译器展开为等价于:
for (auto it = begin(arr); it != end(arr); ++it) {
auto& x = *it;
}对原生数组,编译器使用指针;对 STL 容器,调用 begin()/end() 方法。
语法
三种循环
// for: 已知循环次数
for (int i = 0; i < n; i++) {
std::cout << i << ' ';
}
// while: 条件驱动
while (x > 0) {
x /= 2;
}
// do-while: 至少执行一次
do {
std::cout << "输入正数: ";
std::cin >> num;
} while (num <= 0);break 和 continue
for (int i = 0; i < 10; i++) {
if (i == 3) continue; // 跳过 i=3
if (i == 7) break; // i=7 时退出循环
std::cout << i << ' ';
}
// 输出: 0 1 2 4 5 6break 只能跳出最内层循环。多层跳出需使用标志变量。
range-based for (C++11)
int arr[] = {1, 2, 3, 4, 5};
for (int x : arr) { // 值拷贝,不修改原数组
std::cout << x << ' ';
}
for (int& x : arr) { // 引用,修改原数组
x *= 2;
}
for (const auto& x : arr) { // 只读引用,避免拷贝
std::cout << x << ' ';
}对容器首选
const auto&遍历,既避免拷贝又能保护原数据。
死循环
while (true) {
if (exit_condition) break;
}
// 等价于
for (;;) {
if (exit_condition) break;
}实践
常见循环模式:
| 模式 | 代码 |
|---|---|
| 累加 | sum += arr[i]; |
| 计数 | if (cond) count++; |
| 查找 | if (arr[i] == target) { found = true; break; } |
| 最值 | if (arr[i] > max) max = arr[i]; |
判断素数(优化到 sqrt):
bool isPrime(int n) {
if (n < 2) return false;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) return false;
}
return true;
}
i * i <= n比i <= sqrt(n)更高效——免去浮点运算开销。注意i * i可能 int 溢出,大规模可改用long long i。
力扣:
力扣: 简单遍历题 (遍历+最值)
力扣: 分类统计题 (循环+分类统计)
力扣: while 循环计数题 (while 循环)
力扣: 嵌套循环题 (嵌套循环)
AI 自检提示:询问 AI “编译器通常对循环做哪些优化,为什么 i*i 比 sqrt(n) 更高效”。