C++ 流程控制语句:构建结构化程序的核心逻辑
流程控制语句是结构化编程(Structured Programming)的三大支柱之一(顺序、选择、循环),它们决定了程序“下一步该执行哪一段代码”。C++ 继承了 C 的控制结构,并保持了向后兼容性,同时在现代 C++ 中鼓励更清晰、更安全的写法。
1. 结构化编程三大基本结构(Dijkstra 1968 提出)
- 顺序结构:代码从上到下依次执行(默认)
- 选择结构:根据条件执行不同代码块(if / else / switch)
- 循环结构:重复执行某段代码(for / while / do-while)
goto 被认为破坏结构化(“ spaghetti code”),现代 C++ 强烈不推荐在普通代码中使用。
2. 选择结构(Selection / Branching)
2.1 if / else / else if
最常用、最灵活的选择结构。
if (condition1) {
// ...
} else if (condition2) {
// ...
} else {
// ...
}
现代写法建议(C++17+):
if (auto it = m.find(key); it != m.end()) {
// 使用 it->second
} else {
// 未找到
}
2.2 switch(多路分支)
适合离散值判断(整数、枚举、字符),比多重 if-else 更清晰。
switch (grade) {
case 'A': std::cout << "优秀\n"; break;
case 'B': std::cout << "良好\n"; break;
case 'C':
case 'D': std::cout << "及格\n"; break;
default: std::cout << "不及格\n";
}
C++17 新特性:初始化语句
switch (int code = getErrorCode(); code) {
case 0: /* OK */ break;
case -1: /* 失败 */ break;
default: /* 未知 */ break;
}
注意:
- 缺少
break会贯穿(fall-through),有时故意用(标注[[fallthrough]];C++17+) - 表达式必须是整型/枚举/可转换为整型的类型(C++20 前不能直接用 string)
3. 循环结构(Iteration / Looping)
| 循环类型 | 适用场景 | 至少执行次数 | 条件检查时机 | 现代 C++ 推荐指数 |
|---|---|---|---|---|
for | 已知循环次数、范围遍历 | 0 次 | 进入前 | ★★★★★ |
while | 未知次数、直到条件不满足 | 0 次 | 进入前 | ★★★★☆ |
do-while | 至少执行一次(如菜单、输入验证) | 1 次 | 结束时 | ★★★☆☆ |
| 范围 for | 容器/数组遍历(C++11+) | 0 次 | — | ★★★★★ |
3.1 经典 for 循环(三部分写法)
for (int i = 0; i < 10; ++i) {
// ...
}
C++17+ 带初始化
for (size_t i = 0; auto& elem : vec; ++i) {
// 既能用索引 i,也能用 elem
}
3.2 范围 for(range-based for loop)——现代首选
std::vector<int> v = {1, 2, 3, 4, 5};
// 读
for (int x : v) { ... } // 拷贝
for (const auto& x : v) { ... } // 推荐:避免拷贝
for (auto& x : v) { x *= 2; } // 可修改
// C++20+ 带索引(需要 <ranges> 或第三方)
for (auto [i, elem] : std::views::enumerate(v)) {
std::cout << i << ": " << elem << '\n';
}
3.3 while 与 do-while
while (condition) {
// 可能一次都不执行
}
do {
// 至少执行一次
} while (condition);
经典使用 do-while 的场景:
- 强制用户输入正确格式
- 菜单循环(先显示菜单再判断是否退出)
4. 循环控制语句:改变默认流程
| 语句 | 作用 | 适用范围 | 注意事项 |
|---|---|---|---|
break | 立即跳出当前循环 / switch | for/while/do/switch | 只跳出最近一层循环 |
continue | 跳过本次循环剩余部分,进入下一次 | for/while/do | 不跳出循环,只跳过当前迭代 |
goto | 无条件跳转到标签 | 任意位置 | 强烈不推荐(除极特殊错误处理外) |
return | 立即结束当前函数,返回值 | 函数体内 | 可带返回值,也可 void 函数用 return; |
现代替代 goto 的写法(RAII + 作用域):
// 不要这样写 goto
if (error) goto cleanup;
// 推荐:用作用域 + RAII
{
Resource r1; // 自动析构
if (error1) return error_code;
Resource r2;
if (error2) return error_code;
// 正常逻辑
}
5. 快速对比总结表(面试/复习用)
| 控制结构 | 关键字 | 执行次数 | 典型场景 | 现代 C++ 偏好写法 |
|---|---|---|---|---|
| 单分支 | if | 0~1 | 简单条件判断 | if constexpr (C++17) |
| 多分支 | if-else / switch | 0~1 | 枚举、状态机、菜单 | switch + [[fallthrough]] |
| 计数循环 | for | 0~N | 已知次数、数组遍历 | range-based for + std::views |
| 条件循环 | while | 0~N | 未知次数、读取直到 EOF | while (std::cin >> x) |
| 先执行后判断 | do-while | 1~N | 至少一次(如输入验证) | — |
| 无限循环 | for(;;) / while(true) | 直到 break | 服务器主循环、游戏循环 | for(;;) { … if (quit) break; } |
6. 现代 C++ 推荐的“结构化”心态
- 优先用范围 for 遍历容器
- 用 if 初始化 和 if constexpr 减少嵌套
- 用 structured bindings(C++17)解构 pair/tuple
- 尽量避免深层嵌套(超过 3 层考虑提函数)
- 用 RAII + 早返回 代替 goto 和深层 if-else
- 无限循环用
for(;;)而不是while(1)(更清晰意图)
你现在最常写的循环是哪一种?
项目里有没有特别讨厌的多层嵌套 if / 循环?
或者想看某个具体场景的现代写法对比(比如处理输入验证、状态机、遍历嵌套容器等),可以直接告诉我~