switch仅支持整型、枚举等可隐式转为整型的类型;case值必须为编译期常量;遗漏break将导致fall-through。

switch 不能直接处理浮点数、字符串或自定义类型,只能用于整型、枚举或可隐式转换为整型的类型(如 char、short、int、long、enum、enum class(需配合 underlying_type))。
case 标签必须是常量表达式
每个 case 后面的值必须在编译期就能确定,比如字面量、constexpr 变量、枚举值。运行时变量、函数调用、带变量的表达式都不行:
-
case 42:✅ 合法 -
case 'a':✅ 字符字面量本质是 int -
case MyEnum::Value:✅ 枚举成员(非作用域枚举或有明确底层类型的enum class) -
case x:❌x是普通变量 -
case func():❌ 即使func()返回 constexpr,也不能出现在 case 中(C++17 起仍不支持)
忘记 break 会导致 fall-through(穿透)
这是最常见也最容易被忽视的问题:C++ 的 switch 默认不会在每个 case 结束后自动跳出,而是继续执行下一个 case 的语句,直到遇到 break 或 switch 结束。
int x = 1;
switch (x) {
case 1:
std::cout << "one\n";
case 2:
std::cout << "two\n";
break;
default:
std::cout << "other\n";
}
输出是 one 和 two ——不是只进 case 1。解决方式只有显式写 break;C++17 引入了 [[fallthrough]] 属性,用来明确标记“此处穿透是有意的”,避免编译器警告:
立即学习“C++免费学习笔记(深入)”;
- 没写
break且没加[[fallthrough]]→ 大多数编译器会警告(如 GCC/Clang 的-Wimplicit-fallthrough) - 写了
[[fallthrough]];→ 表明穿透是设计行为,警告消失 -
[[fallthrough]]必须放在会穿透到下个case的语句末尾,且前面必须有分号
default 不是必须的,但强烈建议加上
如果输入值不在任何 case 中,又没写 default,程序就什么也不做——这往往掩盖逻辑漏洞。更危险的是,某些嵌入式或安全敏感场景中,未处理的分支可能引发未定义行为或状态不一致。
- 即使你“确定”所有情况都已覆盖(比如枚举全列),也要加
default,至少写个assert(false)或抛异常 - 对于
enum class,即使你列出了全部枚举项,也不能保证运行时值合法(比如通过reinterpret_cast或内存篡改得到非法值) - 部分静态分析工具(如 clang-tidy)会检查是否遗漏
default,尤其对枚举类型
真正麻烦的地方在于:fall-through 是语言特性而非 bug,但人类直觉默认它该“自动终止”;而 default 看似可选,实际在维护性和健壮性上几乎不可省略。









