switch不匹配时直接执行switch后第一条语句;default非必需,缺省且无匹配则静默跳过;case仅支持整型常量表达式,禁用变量、浮点数、字符串;fall-through是特性但需显式标注[[fallthrough]];性能优势依赖编译器优化与case分布。

switch 语句不匹配时到底跳哪?
它不会自动跳到下一个 case,也不会跳到 default —— 它直接执行 switch 后面第一个语句(即紧跟 { 的那条),除非你显式写 break 或控制流被其他逻辑打断。
常见错误现象:case 1: 里忘了写 break,结果 case 2: 的代码也一起执行了;或者以为没匹配就会进 default,结果发现变量值不在任何 case 中,又没写 default,整个 switch 块就静默跳过了。
- 必须手动用
break终止每个分支,C++ 不像 Python 的match会自动退出 -
default不是必须的,但漏掉它且无匹配时,switch内部什么都不会做 -
default可以放在任意位置(开头、中间、末尾),不是只能在最后
case 标签只能是常量表达式
这意味着你不能写 case x:(x 是变量)、case func():、case arr[i]:,甚至连 case sizeof(int): 都不行 —— 虽然 sizeof 是编译期运算,但 C++ 要求 case 必须是「整型常量表达式」,且值必须能在编译期确定。
使用场景:只适合枚举值、字面量(0、'a'、0xFF)、带 constexpr 的变量(如 constexpr int kErr = -1;)。
立即学习“C++免费学习笔记(深入)”;
- 字符串不能直接用在
case中(C++17 起可用std::string_view+constexpr哈希模拟,但非原生支持) - 浮点数不允许作为
case值(连3.14都不行,哪怕加static_cast<int></int>也不行) - 枚举项可以,但要确保底层类型是整型(
enum class E : int { A = 1 };安全;enum class E { A }底层类型未指定,某些编译器可能报错)
fall-through 是特性,不是 bug
连续多个 case 共享同一段代码,是合法且有意为之的设计。比如处理一组相关状态:case STARTED:、case RUNNING:、case PAUSED: 都想执行日志记录,就可以省略中间的 break。
但现代编译器(GCC/Clang/MSVC)默认会对隐式 fall-through 发出警告(如 -Wimplicit-fallthrough),因为多数时候它是疏忽。
- 显式标注意图更安全:Clang/GCC 支持
[[fallthrough]];(C++17),放在break缺失的位置 - 不要依赖注释(如
// fall through)来抑制警告,不同编译器识别规则不一致 - 如果真想“穿透”,确保所有被穿透的
case分支逻辑上确实等价,否则容易埋下维护陷阱
switch 比 if-else 链快,但只在特定条件下成立
编译器通常把密集、连续的小整数 case(比如 0 到 10)编译成跳转表(jump table),O(1) 查找;而稀疏或跨度大的值(如 case 1:、case 1000:、case 999999:)可能退化为二分查找或链式比较,性能未必优于 if-else。
性能影响还取决于目标平台:嵌入式系统中跳转表会占用更多 ROM;而 if-else 在指令缓存局部性上有时反而更好。
- 别为了“理论上更快”强行把 3 个分支改写成
switch—— 编译器对短链的优化已经很成熟 - 如果
case值来自用户输入或配置文件,且范围不可控,优先考虑std::map或哈希查找,而不是硬塞进switch - 用
[[likely]]/[[unlikely]](C++20)标注高频分支,比调整case顺序对现代 CPU 更有效
最容易被忽略的是:switch 的判别表达式只计算一次,而 if-else 链里每个条件都可能重新求值 —— 如果表达式有副作用(比如函数调用),这个差异会直接影响行为。











