c++ - 为什么 switch 构造中的声明是合法的?

标签 c++

我发现了多个关于在 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在声明后在同一范围或子范围内的任何点都可见。
没有什么会导致两种情况之间的范围变化,所以 ifalse 中仍然可见情况不管是否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 a case label is considered a jump in this respect.

关于c++ - 为什么 switch 构造中的声明是合法的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63021917/

相关文章:

c++ - 无法生成随机数?

c++ - 为什么我必须在 C++ 中按 enter 两次才能获取行?

c++ - 找出内存被消耗的地方

c++ - 通过作为类的公共(public)成员的两个函数传递一个函数作为参数

c++ - 需要 C++ boost::optional 的帮助

c++ - 如何使用 move 语义链接函数?

c++ - 模板中的向下转型

c++ - 设置整个数组值的最简单方法是什么?

c++ - 为什么我的套接字 connect() 在 WSASetSocketSecurity() 之后失败?

c++ - 奇怪的 C++ 编译器问题