C++
编译器支持
独立与宿主
语言
标准库
标准库头文件
具名要求
功能特性测试宏 (C++20)
语言支持库
概念库 (C++20)
诊断库
内存管理库
元编程库 (C++11)
通用工具库
容器库
迭代器库
范围库 (C++20)
算法库
字符串库
文本处理库
数值库
日期和时间库
输入/输出库
文件系统库 (C++17)
并发支持库 (C++11)
执行控制库 (C++26)
技术规范
符号索引
外部库
[编辑] C++ 语言
通用主题
预处理器
注释
关键字
转义序列
流程控制
条件执行语句
if
switch
迭代语句(循环)
for
范围 for (C++11)
while
do-while
跳转语句
continue
goto
break
return
函数
函数声明
Lambda 函数表达式
inline 说明符
动态异常说明 (C++17 前*)
noexcept 说明符 (C++11)
异常
throw 表达式
try 块
catch 处理块
命名空间
命名空间声明
命名空间别名
类型
基础类型
枚举类型
函数类型
类/结构体类型
联合体类型
说明符
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
存储期说明符
初始化
默认初始化
值初始化
零初始化
复制初始化
直接初始化
聚合初始化
列表初始化 (C++11)
常量初始化
引用初始化
表达式
值类别
求值顺序
运算符
运算符优先级
替代表示
字面量
布尔 - 整数 - 浮点
字符 - 字符串 - nullptr (C++11)
用户定义 (C++11)
实用工具
属性 (C++11)
类型
typedef 声明
类型别名声明 (C++11)
转型
隐式转换
static_cast
const_cast
显式转换
dynamic_cast
reinterpret_cast
内存分配
new 表达式
delete 表达式
类
类声明
构造函数
this 指针
访问说明符
friend 说明符
类特定的函数属性
虚函数
override 说明符 (C++11)
final 说明符 (C++11)
explicit (C++11)
static
特殊成员函数
默认构造函数
复制构造函数
移动构造函数 (C++11)
复制赋值
移动赋值 (C++11)
析构函数
模板
类模板
函数模板
模板特化
形参包 (C++11)
杂项
内联汇编
C++ 的历史
[编辑] 语句
标号
标号 : 语句
表达式语句
表达式 ;
复合语句
{ 语句... }
选择语句
if
switch
循环语句
while
for
do while
范围 for (C++11)
展开语句
template for (C++26)
跳转语句
break
return
continue
goto
断言语句
contract_assert (C++26)
声明语句
声明 ;
Try 块
try 块
事务内存
synchronized 等 (TM TS)
[编辑]
根据条件的值,将控制权传递给若干语句之一。
目录
1 语法
2 条件
2.1 表达式
2.2 声明
2.2.1 非结构化绑定声明
2.2.2 结构化绑定声明
2.3 类型
3 标签
4 控制流转移
5 带初始化器的 switch 语句
6 注解
7 关键字
8 示例
9 缺陷报告
10 参阅
11 外部链接
语法
attr (可选) switch ( init-statement (可选) condition ) statement
attr
-
(C++11 起) 任意数量的属性
初始化语句
-
(C++17 起) 以下任意一项一个 表达式语句(可以是空语句 ;)
一个 简单声明,通常是带有初始化器的变量声明,但它也可以声明任意数量的变量或 结构化绑定
一个别名声明
(C++23 起)
注意,任何 初始化语句 都必须以分号结尾。这就是为什么它通常被非正式地描述为后面跟有分号的表达式或声明。
条件
-
一个条件
语句
-
一个语句(通常是复合语句)
条件
条件可以是一个表达式,也可以是一个简单声明。
如果它在语法上可以解析为结构化绑定声明,则它会被解释为结构化绑定声明。
(C++26 起)
如果它在语法上可以解析为表达式,则将其视为表达式。否则,将其视为不是结构化绑定声明的声明(C++26 起)。
当控制流到达条件时,该条件会产生一个值,该值用于决定控制流将跳转到哪个标签。
表达式
如果 condition 是表达式,它产生的值即为该表达式的值。
声明
如果 condition 是简单声明,它产生的值即为判定变量的值(见下文)。
非结构化绑定声明
该声明有以下限制:
在语法上符合以下形式之一:
类型说明符序列 声明符 = 赋值表达式
(C++11 前)
属性说明符序列(可选) 声明说明符序列 声明符 大括号或等号初始化器
(C++11 起)
声明符不能指定函数或数组。
类型说明符序列(C++11 前)声明说明符序列只能包含类型说明符和 constexpr,且它(C++11 起)不能定义类或枚举。
该声明的决定变量是所声明的变量。
结构化绑定声明
该声明有以下限制:
其初始化器中的表达式不能是数组类型。
声明说明符序列只能包含类型说明符和 constexpr。
该声明的决定变量是该声明引入的虚构变量 e。
(C++26 起)
类型
condition 只能产生以下类型的值
整型
枚举类型
类类型
如果产生的值是类类型,则它会被按语境隐式转换为整型或枚举类型。
如果(可能经过转换的)类型会受到 整型提升 的影响,则产生的值会被转换为提升后的类型。
标号
switch 语句中的任何语句都可以被冠以以下一个或多个标签
attr (可选) case constant-expression :
(1)
attr (可选) default:
(2)
attr
-
(C++11 起) 任意数量的属性
constant-expression
-
switch 条件经调整后的类型的 转换的常量表达式
case 或 default 标签关联到包围它的最内层 switch 语句。
如果满足以下任一条件,程序为非良构:
switch 语句不能与多个其 constant-expression 在转换后具有相同值的 case 标签关联。
switch 语句不能与多个 default 标签关联。
控制流转移
当 switch 语句的条件产生一个(可能经过转换的)值时
如果某一个关联的 case 标签常量具有相同的值,则控制流会传递到被匹配的 case 标签所标示的语句。
否则,如果存在关联的 default 标签,则控制流会传递到由该 default 标签所标示的语句。
否则,switch 语句中的所有语句都不会被执行。
case 和 default 标签本身不会改变控制流。若要从 switch 语句的中途退出,请参见 break 语句。
编译器可能会对贯穿(fallthrough,即在没有 break 的情况下到达下一个 case 或 default 标签)发出警告,除非属性 [[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 语句等价于
{
初始化语句
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
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 无法被提升
不提升这些类型的 condition
CWG 2629
C++98
condition 可以是浮点型变量的声明
禁止
参见
C 文档(针对 switch)
外部链接
1.
使用 Duff 设备(Duff's Device)进行循环展开
2.
Duff 设备可用于在 C/C++ 中实现协程