我发现了多个关于在 switch
中定义变量的问题。构造,但我还没有找到这个问题的明确答案。
C++ Primer 一书的第 5.3.2 章说如下:
As we’ve seen, execution in a switch can jump across case labels. When execution jumps to a particular case, any code that occurred inside the switch before that label is ignored.
考虑到这些信息,我不明白为什么下面的例子是合法的。如果控制跳转到
false
情况下,它应该忽略 true
案件。这意味着,分配给 i
应该是非法的,因为它从未被宣布过。为什么这种构造是合法的?case true:
int i;
break;
case false:
i = 42;
break;
最佳答案
声明是编译时的事情,运行时发生的事情与这个事实无关。 i
在声明后在同一范围或子范围内的任何点都可见。
没有什么会导致两种情况之间的范围变化,所以 i
在 false
中仍然可见情况不管是否true
案件执行。
这就是为什么您可能会看到匿名块 ( { }
) 用于在 switch 案例中人为地限制范围。这是为了防止这个潜在的问题(尽管在这种情况下这不是问题)。
case true: {
int i;
break;
} // Closing this block causes the end of i's lifetime.
case false: {
i = 42; // Compile-time error; i is no longer in scope.
break;
}
请注意,您的代码仅通过初始化 i
就变得非法。 .跳转不能在任一方向跨越初始化。case true:
int i = 0;
break;
case false: // error: jump to case label crosses initialization
i = 42;
break;
此外,任何不是 trivial 类型的变量即使没有显式初始化,也不能具有跨越生命周期的情况。case true:
std::string i;
break;
case false: // error: jump to case label crosses initialization
i = "42";
break;
这种情况下的解决方法是使用匿名块来限制 i
的声明范围。不跨越多个案例。相关标准:
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 variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has scalar type, class type with a trivial default constructor and a trivial destructor, a cv-qualified version of one of these types, or an array of one of the preceding types and is declared without an initializer.
-- C++14 (N4296) [stmt.dcl.3]
关于跳转的脚注 (*):
The transfer from the condition of a
switch
statement to acase
label is considered a jump in this respect.
关于c++ - 为什么 switch 构造中的声明是合法的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63021917/