C++中switch
C++中switch...case绕过变量初始化
之前和同事遇到一个编译错误,顺便了解了一下标签下变量的作用域与绕过初始化的问题。总结就是,要在switch语句中,除非声明包含在块中,否则不能跳过带有初始值设定项的声明。注意这里C++的表现和C语言不同。
编译环境
Visual Studio 2022 / v143 / C++17
下面的代码是不能够通过编译的
#include <iostream>
int main()
{
switch (0) {
case 1:
int b = 1;
break;
default:
break;
}
return 0;
}
如果进行了初始化操作,但是此时跳过了该变量的初始化是非法的操作, 造成无法预料的结果。
不限于switch语句。使用"goto"跳过初始化也会遇到错误。
goto LABEL; // Error 跳过初始化
int j = 0;
LABEL:
;
return 0;
解决
给case下加个{}作用域就没问题了。这样变量的生存期就只限于单个case标签。
#include <iostream>
int main()
{
switch (0) {
case 1:
{
int b = 1;
} break;
default:
}
return 0;
}
下面的代码是能够正常编译的。
#include <iostream>
int main()
{
switch (0) {
case 1:
int b; // 定义,没有初始化。
break;
default:
b = 1;
std::cout << b;
}
return 0;
}
//
#include <iostream>
int main()
{
switch (0) {
case 1:
int b; // POD类型定义,没有初始化。
b = 1; // 这里不会执行
break;
default:
b = 1; // b赋值为1
std::cout << b << std::endl;
break;
}
return 0;
}
C++文档中指出
It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A program that jumps from a point where a local variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has POD type (3.9) and is declared without an initializer.
大致意思是,如果一个程序执行过程中,从A点跳到B点,中间有变量定义时候进行初始化,也就是跳过了具有自动存储周期的变量的初始化是非法的操作。除非变量具有POD类型,没有初始化器。
所以上面符合规则,是可以编译的。
POD
POD 是 Plain Old Data 的缩写。普通类型。两个系统进行交换数据,如果没有办法对数据进行语义检查和解释,那就只能以非常底层的数据形式进行交互,而拥有 POD 特征的类或者结构体通过二进制拷贝后依然能保持数据结构不变。
可以用 is_pod::value 来判断是不是POD类型。
-
内存布局有序,成员是public,并且没有基类,没有构造、析构函数和虚函数。
-
静态成员在这些规则下也是。
-
int, char, wchar_t, bool, float, double是POD类型,这些类型的long/short and signed/unsigned版本也是;
- trivially copyable types (C style structs should all be trivially copyable)
-
enums枚举类型;
-
指针(包括函数指针和成员指针)都是POD类型;

浙公网安备 33010602011771号