命名空间
变体
操作

switch 语句

来自 cppreference.cn
< cpp‎ | language
 
 
C++ 语言
通用主题
流控制
条件执行语句
if
switch
迭代语句(循环)
for
范围 for (C++11 起)
跳转语句
函数
函数声明
Lambda 函数表达式
inline 说明符
动态异常规范 (于 C++17* 弃用)
noexcept 说明符 (C++11 起)
异常
命名空间
类型
说明符
const/volatile
decltype (C++11 起)
auto (C++11 起)
constexpr (C++11 起)
consteval (C++20 起)
constinit (C++20 起)
存储期说明符
初始化
表达式
替用表示
字面量
布尔 - 整型 - 浮点
字符 - 字符串 - nullptr (C++11 起)
用户定义 (C++11 起)
工具
属性 (C++11 起)
类型
typedef 声明
类型别名声明 (C++11 起)
转型
内存分配
类特有函数属性
虚函数
override 说明符 (C++11 起)  
final 说明符 (C++11 起)
explicit (C++11 起)
static

特殊成员函数
模板
模板特化
形参包 (C++11 起)
杂项
 
 

根据条件的值,将控制转移到若干语句之一。

内容

[编辑] 语法

attr (可选) switch ( init-statement (可选) condition ) statement
attr - (C++11 起) 任意数量的 属性
init-statement - (C++17 起) 以下任何一种
(C++23 起)

请注意,任何 init-statement 必须以分号结尾。这就是为什么它通常被非正式地描述为表达式或声明后跟分号。

condition - 一个 条件
statement - 一条语句(通常是复合语句)

[编辑] 条件

condition 可以是表达式简单声明

  • 如果它可以被语法解析为结构化绑定声明,则它被解释为结构化绑定声明。
(C++26 起)
  • 如果它可以被语法解析为表达式,则它被视为表达式。否则,它被视为声明,这不是结构化绑定声明(C++26 起)

当控制到达条件时,该条件将产生一个值,该值用于确定控制将转到哪个标签。

[编辑] 表达式

如果 condition 是表达式,则它产生的值是表达式的值。

[编辑] 声明

如果 condition 是简单声明,则它产生的值是决策变量的值(见下文)。

[编辑] 非结构化绑定声明

该声明具有以下限制

  • 语法上符合以下形式
  • type-specifier-seq declarator = assignment-expression
(直到 C++11)
  • attribute-specifier-seq(可选) decl-specifier-seq declarator brace-or-equal-initializer
(C++11 起)

声明的决策变量是声明的变量。

结构化绑定声明

该声明具有以下限制

声明的决策变量是由声明引入的虚构变量 e

(C++26 起)

[编辑] 类型

condition 只能产生以下类型

  • 整型
  • 枚举类型
  • 类类型

如果产生的值是类类型,则它在语境中隐式转换为整型或枚举类型。

如果(可能转换后的)类型受整型提升约束,则产生的值将转换为提升后的类型。

[编辑] 标签

switch 语句中的任何语句都可以用一个或多个以下标签标记

attr (可选) case constant-expression : (1)
attr (可选) default: (2)
attr - (C++11 起) 任意数量的 属性
constant-expression - switch 条件调整类型的转换后的常量表达式


casedefault 标签与包围它的最内层 switch 语句相关联。

如果满足以下任何条件,则程序是非良构的

  • switch 语句与多个 case 标签相关联,这些标签的 constant-expression s 在转换后具有相同的值。
  • switch 语句与多个 default 标签相关联。

[编辑] 控制流转移

switch 语句的条件产生(可能转换后的)值时

  • 如果关联的 case 标签常量之一具有相同的值,则控制传递到由匹配的 case 标签标记的语句。
  • 否则,如果存在关联的 default 标签,则控制传递到由 default 标签标记的语句。
  • 否则,switch 语句中的任何语句都不会被执行。

casedefault 标签本身不会改变控制流。要从 switch 语句的中间退出,请参见 break 语句

编译器可能会对直落(在没有 break 的情况下到达下一个 casedefault 标签)发出警告,除非属性 [[fallthrough]] 紧接在 case 标签之前出现,以表明直落是故意的(C++17 起)

switch (1)
{
    case 1:
        std::cout << '1'; // prints "1",
    case 2:
        std::cout << '2'; // then prints "2"
}
switch (1)
{
    case 1:
        std::cout << '1'; // prints "1"
        break;            // and exits the switch
    case 2:
        std::cout << '2';
        break;
}

switch 带有初始化器的语句

如果使用了 init-statement,则 switch 语句等效于

{
init-statement
switch ( condition ) statement

}

除了由 init-statement 声明的名称(如果 init-statement 是声明)和由 condition 声明的名称(如果 condition 是声明)位于同一作用域中,该作用域也是 statement 的作用域。

(C++17 起)

[编辑] 注解

由于不允许控制转移进入变量的作用域,因此如果在 statement 内遇到声明语句,则必须将其限定在自己的复合语句中

switch (1)
{
    case 1:
        int x = 0; // initialization
        std::cout << x << '\n';
        break;
    default:
        // compilation error: jump to default:
        // would enter the scope of 'x' without initializing it
        std::cout << "default\n";
        break;
}
switch (1)
{
    case 1:
        {
            int x = 0;
            std::cout << x << '\n';
            break;
        } // scope of 'x' ends here
    default:
        std::cout << "default\n"; // no error
        break;
}

[编辑] 关键字

switch, case, default

[编辑] 示例

以下代码展示了 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++ 中实现协程