为什么在switch语句中声明变量是允许的,但不允许声明+初始化?

3
  1. 为什么在switch语句的一个case中声明+初始化变量是不允许的并会出现错误,但如果在一行上声明它然后在另一行上分配一个值,则可以编译通过?
  2. 为什么在先前的case中声明的变量可以在另一个匹配的case中使用(操作),即使先前的case语句没有执行!

以下代码编译时没有错误或警告:

char ch; cin>> ch;
switch(ch)
{
    case 'a':
        int x;  // How come this is ok but not this(int x = 4;)?
        x = 4;
        cout<< x << endl;
        break;
    case 'b':
        x += 1;  // x is in scope but its declaration did not execute!
        cout<< x << endl;
        break;
    case 'c': 
        x += 1;
        cout<< x << endl;
        break;
}

我希望 case 'b' 或者 case 'c' 不知道有一个叫做 x 的变量。但是我知道变量 x 在 case b 和 case c 中仍然在作用域内。

case 'a' 输出 4

case 'b' 输出 1

case 'c' 输出 1

编辑:不,被标记为可能重复的其他问题线程没有回答我的问题。

  1. 为什么变量 x 不能定义和初始化?如果允许这样做会产生什么问题,导致不被允许这样做?

如果只允许在一个语句中定义变量,那么变量将在匹配的 case 中使用,同时会使用其中的任何垃圾值;与声明+初始化变量有什么区别呢?


2
你为什么在问题标签中同时打了C和C++的标签?它们是非常不同的语言,即使没有cout的内容,也不能编译成C。第一行被注释的代码在C中违反了约束条件。 - R.. GitHub STOP HELPING ICE
在 C 语言中,单独在 switch 中声明是不允许的,但是在 switch 中创建的不同作用域中声明是可以的。例如:switch(ch) { case 'a': { int x; .. } case 'b' : ... } - David C. Rankin
看起来很合理。int x;是一个声明,x在switch语句中变得可见。另一方面,对x进行操作取决于选择哪条路径。因此,将声明和初始化结合在一起可能会产生误导。如果只有在选择了某个路径时才进行初始化,那么不允许这样做是有道理的。 - doug
1
可能是为什么不能在switch语句中声明变量?的重复问题。 - Hong Ooi
1
@topcat 实际上它确实可以(虽然不是第一个):https://dev59.com/3HVD5IYBdhLWcg3wGHeu#19830820 - andreee
显示剩余4条评论
1个回答

4

case标签作为goto语句的目标。

C++标准在[stmt.dcl]/3中规定:

可以转移到块中,但不能绕过具有初始化的声明。

因此,以下内容将失败:

case 'a':
    int x = 4; //will fail

而以下内容不会失败:
case 'a':
    int x;  // this is ok 
    x = 4;

针对OP的编辑回复:

在这种情况下,只有声明使得x在整个switch语句中可见,因为没有括号{}将其括起来。 因此,x也可以与其他case一起使用,尽管编译器会警告未初始化的使用。请注意,读取未初始化变量是未定义行为。

回答您问题的最后一部分:
假设允许带有初始化的声明,则意味着必须在其他case中使用x的特定值(在本例中为4)。 然后,似乎执行了多个案例的代码。因此,这是不允许的。


初始化是在运行时还是编译时完成的? - topcat
2
@topcat 运行时。如果您有一个具有构造函数的类(例如 std::string x;),则会出现相同的问题,因为构造函数将执行初始化。 - 1201ProgramAlarm
1
@topcat:根据您的编辑更新了帖子。 - P.W

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接