我一直在想这个问题——为什么不能在switch语句的case标签后面声明变量呢?在c++中,你可以在任何地方声明变量(并且在第一次使用时声明它们显然是一件好事),但以下仍然不能工作:

switch (val)  
{  
case VAL:  
  // This won't work
  int newVal = 42;  
  break;
case ANOTHER_VAL:  
  ...
  break;
}  

上面给了我以下错误(MSC):

'newVal'的初始化被'case'标签跳过

这在其他语言中似乎也是一个限制。为什么这是一个问题?


当前回答

c++标准有: 可以将其转移到块中,但不能绕过带有初始化的声明。如果一个程序从一个具有自动存储持续时间的局部变量不在作用域中的点跳转到它在作用域中的点,那么该程序就是病态形式的,除非该变量具有POD类型(3.9),并且声明时没有初始化式(8.5)。

说明此规则的代码:

#include <iostream>

using namespace std;

class X {
  public:
    X() 
    {
     cout << "constructor" << endl;
    }
    ~X() 
    {
     cout << "destructor" << endl;
    }
};

template <class type>
void ill_formed()
{
  goto lx;
ly:
  type a;
lx:
  goto ly;
}

template <class type>
void ok()
{
ly:
  type a;
lx:
  goto ly;
}

void test_class()
{
  ok<X>();
  // compile error
  ill_formed<X>();
}

void test_scalar() 
{
  ok<int>();
  ill_formed<int>();
}

int main(int argc, const char *argv[]) 
{
  return 0;
}

显示初始化器效果的代码:

#include <iostream>

using namespace std;

int test1()
{
  int i = 0;
  // There jumps fo "case 1" and "case 2"
  switch(i) {
    case 1:
      // Compile error because of the initializer
      int r = 1; 
      break;
    case 2:
      break;
  };
}

void test2()
{
  int i = 2;
  switch(i) {
    case 1:
      int r;
      r= 1; 
      break;
    case 2:
      cout << "r: " << r << endl;
      break;
  };
}

int main(int argc, const char *argv[]) 
{
  test1();
  test2();
  return 0;
}

其他回答

试试这个:

switch (val)
{
    case VAL:
    {
        int newVal = 42;
    }
    break;
}

在阅读了所有的答案和更多的研究之后,我得到了一些东西。

Case statements are only 'labels'

在C语言中,根据规范,

§6.8.1标签声明:

labeled-statement:
    identifier : statement
    case constant-expression : statement
    default : statement

在C语言中,没有任何子句允许“标记声明”。这不是语言的一部分。

So

case 1: int x=10;
        printf(" x is %d",x);
break;

这将不会编译,请参阅http://codepad.org/YiyLQTYw。GCC给出一个错误:

label can only be a part of statement and declaration is not a statement

Even

  case 1: int x;
          x=10;
            printf(" x is %d",x);
    break;

这也不是编译,参见http://codepad.org/BXnRD3bu。这里我也得到了同样的错误。


在c++中,根据规范,

允许标记-声明,但不允许标记-初始化。

见http://codepad.org/ZmQ0IyDG。


这种情况的解是二

使用{}使用新的作用域 案例1: { int x = 10; Printf (" x是%d", x); } 打破; 或者使用带标签的虚拟语句 案例1:; int x = 10; Printf (" x是%d",x); 打破; 在switch()之前声明变量,并在case语句中用不同的值初始化它,如果它满足您的要求 main () { int x;//在前面声明 开关(a) { 情况1:x=10; 打破; 情况2:x=20; 打破; } }


还有更多关于switch语句的东西

永远不要在switch中写入任何不属于任何标签的语句,因为它们永远不会被执行:

switch(a)
{
    printf("This will never print"); // This will never executed

    case 1:
        printf(" 1");
        break;

    default:
        break;
}

见http://codepad.org/PA1quYX3。

Case语句只是标签。这意味着编译器将把它解释为直接跳转到标签。在c++中,这里的问题是作用域问题。花括号将作用域定义为switch语句中的所有内容。这意味着您留下了一个作用域,在这个作用域中,将跳过初始化进一步跳转到代码中。

正确的处理方法是定义一个特定于case语句的作用域,并在其中定义变量:

switch (val)
{   
case VAL:  
{
  // This will work
  int newVal = 42;  
  break;
}
case ANOTHER_VAL:  
...
break;
}

交换机的整个部分是一个单独的声明上下文。你不能像那样在case语句中声明变量。试试这个吧:

switch (val)  
{  
case VAL:
{
  // This will work
  int newVal = 42;
  break;
}
case ANOTHER_VAL:  
  ...
  break;
}

有趣的是,这很好:

switch (i)  
{  
case 0:  
    int j;  
    j = 7;  
    break;  

case 1:  
    break;
}

... 但这不是:

switch (i)  
{  
case 0:  
    int j = 7;  
    break;  

case 1:  
    break;
}

我得到一个修复足够简单,但我不明白为什么第一个例子不打扰编译器。正如之前所提到的(2年前的呵呵),声明不是导致错误的原因,即使有逻辑。初始化是问题所在。如果变量在不同的行上被初始化和声明,它将被编译。