switch
语句
根据条件的值,将控制转移到若干语句之一。
内容 |
[编辑] 语法
attr (可选) switch ( init-statement (可选) condition ) statement |
|||||||||
attr | - | (C++11 起) 任意数量的 属性 | ||
init-statement | - | (C++17 起) 以下任何一种
请注意,任何 init-statement 必须以分号结尾。这就是为什么它通常被非正式地描述为表达式或声明后跟分号。 | ||
condition | - | 一个 条件 | ||
statement | - | 一条语句(通常是复合语句) |
[编辑] 条件
|
(C++26 起) |
- 如果它可以被语法解析为表达式,则它被视为表达式。否则,它被视为声明,这不是结构化绑定声明(C++26 起)。
当控制到达条件时,该条件将产生一个值,该值用于确定控制将转到哪个标签。
[编辑] 表达式
如果 condition 是表达式,则它产生的值是表达式的值。
[编辑] 声明
如果 condition 是简单声明,则它产生的值是决策变量的值(见下文)。
[编辑] 非结构化绑定声明
该声明具有以下限制
- 语法上符合以下形式
|
(直到 C++11) |
|
(C++11 起) |
声明的决策变量是声明的变量。
结构化绑定声明该声明具有以下限制 声明的决策变量是由声明引入的虚构变量 e。 |
(C++26 起) |
[编辑] 类型
condition 只能产生以下类型
- 整型
- 枚举类型
- 类类型
如果产生的值是类类型,则它在语境中隐式转换为整型或枚举类型。
如果(可能转换后的)类型受整型提升约束,则产生的值将转换为提升后的类型。
[编辑] 标签
switch 语句中的任何语句都可以用一个或多个以下标签标记
attr (可选) case constant-expression : |
(1) | ||||||||
attr (可选) default: |
(2) | ||||||||
attr | - | (C++11 起) 任意数量的 属性 |
constant-expression | - | switch 条件调整类型的转换后的常量表达式 |
case 或 default 标签与包围它的最内层 switch 语句相关联。
如果满足以下任何条件,则程序是非良构的
- switch 语句与多个 case 标签相关联,这些标签的 constant-expression s 在转换后具有相同的值。
- switch 语句与多个 default 标签相关联。
[编辑] 控制流转移
当 switch 语句的条件产生(可能转换后的)值时
- 如果关联的 case 标签常量之一具有相同的值,则控制传递到由匹配的 case 标签标记的语句。
- 否则,如果存在关联的 default 标签,则控制传递到由 default 标签标记的语句。
- 否则,switch 语句中的任何语句都不会被执行。
case 和 default 标签本身不会改变控制流。要从 switch 语句的中间退出,请参见 break 语句。
编译器可能会对直落(在没有 break 的情况下到达下一个 case 或 default 标签)发出警告,除非属性 [[fallthrough]]
紧接在 case 标签之前出现,以表明直落是故意的(C++17 起)。
switch 带有初始化器的语句如果使用了 init-statement,则 switch 语句等效于
除了由 init-statement 声明的名称(如果 init-statement 是声明)和由 condition 声明的名称(如果 condition 是声明)位于同一作用域中,该作用域也是 statement 的作用域。 |
(C++17 起) |
[编辑] 注解
由于不允许控制转移进入变量的作用域,因此如果在 statement 内遇到声明语句,则必须将其限定在自己的复合语句中
[编辑] 关键字
[编辑] 示例
以下代码展示了 switch 语句的几种用法
#include <iostream> int main() { const int i = 2; switch (i) { case 1: std::cout << '1'; case 2: // execution starts at this case label std::cout << '2'; case 3: std::cout << '3'; [[fallthrough]]; // C++17 attribute to silent the warning on fallthrough case 5: std::cout << "45"; break; // execution of subsequent statements is terminated case 6: std::cout << '6'; } std::cout << '\n'; switch (i) { case 4: std::cout << 'a'; default: std::cout << 'd'; // there are no applicable constant expressions // therefore default is executed } std::cout << '\n'; switch (i) { case 4: std::cout << 'a'; // nothing is executed } // when enumerations are used in a switch statement, many compilers // issue warnings if one of the enumerators is not handled enum color { RED, GREEN, BLUE }; switch (RED) { case RED: std::cout << "red\n"; break; case GREEN: std::cout << "green\n"; break; case BLUE: std::cout << "blue\n"; break; } // the C++17 init-statement syntax can be helpful when there is // no implicit conversion to integral or enumeration type struct Device { enum State { SLEEP, READY, BAD }; auto state() const { return m_state; } /* ... */ private: State m_state{}; }; switch (auto dev = Device{}; dev.state()) { case Device::SLEEP: /* ... */ break; case Device::READY: /* ... */ break; case Device::BAD: /* ... */ break; } // pathological examples // the statement does not have to be a compound statement switch (0) std::cout << "this does nothing\n"; // labels do not require a compound statement either switch (int n = 1) case 0: case 1: std::cout << n << '\n'; }
输出
2345 d red 1
[编辑] 缺陷报告
以下行为变更缺陷报告被追溯应用于先前发布的 C++ 标准。
DR | 应用于 | 已发布行为 | 正确行为 |
---|---|---|---|
CWG 1767 | C++98 | 类型不服从condition s 整型提升的条件无法提升 |
不提升 这些类型的 condition s |
CWG 2629 | C++98 | condition 可以是浮点变量的声明 | 已禁止 |
[编辑] 参见
C 文档 关于 switch
|
[编辑] 外部链接
1. | 使用 Duff 设备进行循环展开 |
2. | Duff 设备可用于在 C/C++ 中实现协程 |