交换机中的条件初始化

时间:2012-11-16 11:32:53

标签: c++ initialization switch-statement

为什么这段代码片段运行良好

void foo(int i)
{
    switch(i) {
    case 1:
    {
        X x1;
        break;
    }
    case 2:
        X x2;
        break;
    }
}

而下面给出了编译错误('case'标签跳过'x1'的初始化)?

void foo(int i)
{
    switch(i) {
    case 1:
        X x1;
        break;
    case 2:
        X x2;
        break;
    }
}

据我所知,使用大括号引入了一个新的范围,因此在我们打开它的开头大括号之前,不会为x1分配存储空间。但x2仍然在一个案例标签内初始化,没有括号。这不应该是一个错误吗?

我认为在两个代码片段

中都可以有条件地跳过x2的初始化

5 个答案:

答案 0 :(得分:7)

1:有效

 case 1:
        {
        X x1;
        break;
        }

如果没有达到条件,x1 不能被任何其他语句使用,因此不会出现运行时错误。 x1并不试图在大括号外存在。


2:无效

 switch(i) {
    case 1:
        X x1; //don't break
        i = 2;
        ...
        ...
        ...
     case 2:
        x1.someOperation()

 }

在上文中,如果i最初为2,则会在构建对象的x1.someOperation()之前点击X x1

如果允许编译,它会抛出运行时错误,具体取决于情况:1 是否在2之前执行,(对象是建造)。因此,编译器不允许它。


普通旧数据类型允许使用相同的内容,不能具有用户定义的构造函数。

答案 1 :(得分:4)

请注意,仅当X为非POD时才会出现错误。如果X是POD,那么您将不会收到任何错误(当您不使用大括号时)。

如果是非POD,则不能跳过在同一范围内声明的变量的初始化。当你不使用大括号时会导致编译错误,因为switch允许你跳过这些变量的初始化,但同时它使它们可以在所有变量中使用它下方的case标签。这很危险。

沿着这一行思考:如果i2,则控件将直接跳转到第二个case而不初始化x1,然后您就可以在第二种情况下使用x1,即使它未初始化。这没有意义。因此,该语言要求它是一个错误。


顺便说一下,要了解POD和非POD是什么,请参阅以下主题:

答案 2 :(得分:2)

一般的想法是每个case不是一个孤立的范围:case 2下的代码可以引用x1变量,因为它之前已在同一范围内声明(即:整个switch块:当然,它不会被初始化,并且会导致错误。

添加花括号实际上是在分割每个case的范围,允许您在case 1中声明无法在其外部引用的变量。

答案 3 :(得分:0)

在条件语句中创建变量不是一个好主意。我建议您在switch语句之外创建变量,然后根据i上的条件将值赋值给它:

void foo(int i) {

    X x1;

    switch(i) {
        case 1:
            x1 = ...;
            break;
        case 2:
            x1 = ...;
            break;
    }
}

答案 4 :(得分:0)

在失败的版本中,x1的声明在case 2:标签之后的几行之前不会超出范围。那就是问题所在。 x2的声明是可以的,因为声明与其范围的结尾之间没有case标签。