十字架初始化有什么迹象?

时间:2010-03-06 13:53:39

标签: c++ initialization

请考虑以下代码:

#include <iostream>
using namespace std;

int main()
{
    int x, y, i;
    cin >> x >> y >> i;
    switch(i) {
        case 1:
            // int r = x + y; -- OK
            int r = 1; // Failed to Compile
            cout << r;
            break;
        case 2:
            r = x - y;
            cout << r;
            break;
    };
}

G ++抱怨crosses initialization of 'int r'。我的问题是:

  1. 什么是crosses initialization
  2. 为什么第一个初始化程序x + y通过编译,但后来失败了?
  3. 所谓的crosses initialization
  4. 有什么问题

    修改
    我知道我应该使用括号来指定r的范围,但我想知道为什么,例如为什么在多案例切换语句中无法定义非POD。

    感谢。

4 个答案:

答案 0 :(得分:92)

int r = x + y;的版本也不会编译。

问题是r有可能在没有执行初始化程序的情况下进入范围。如果您完全删除了初始化程序(即该行将显示为int r;),则代码将编译正常。

您可以做的最好的事情是限制变量的范围。这样你就可以满足编译器和阅读器的需要。

switch(i)
{
case 1:
    {
        int r = 1;
        cout << r;
    }
    break;
case 2:
    {
        int r = x - y;
        cout << r;
    }
    break;
};

标准说(6.7 / 3):

  

可以转换为块,但不能以初始化绕过声明的方式。从具有自动存储持续时间的局部变量不在范围内的点跳转到其在范围内的点的程序是不正确的,除非该变量具有POD类型(3.9)并且在没有初始化器(8.5)的情况下声明。

答案 1 :(得分:35)

您应该将case的内容放在括号中以给它范围,这样就可以在其中声明局部变量:

switch(i) {
    case 1:
        {
            // int r = x + y; -- OK
            int r = 1; // Failed to Compile
            cout << r;
        }
        break;
    case 2:
        ...
        break;
};

答案 2 :(得分:3)

可以转换为块,但不能以初始化绕过声明的方式。从具有自动存储持续时间的局部变量不在范围内的点跳转到其在范围内的点的程序是不正确的,除非变量具有POD类型并且在没有初始化器的情况下声明。

[Example: Code:

void f()
{
  // ...
  goto lx;    // ill-formed: jump into scope of `a'
  // ...
 ly:
    X a = 1;
  // ...
 lx:
   goto ly;    // ok, jump implies destructor
 // call for `a' followed by construction
 // again immediately following label ly
}

--end example]

从switch语句的条件转移到case标签被认为是这方面的跳跃。

答案 3 :(得分:0)

我建议您在r声明之前宣传您的switch变量。如果要在case块中使用变量(或相同的变量名但使用不同的用法),请在switch语句之前定义它:

#include <iostream>
using namespace std;

int main()
{
    int x, y, i;
    cin >> x >> y >> i;
// Define the variable before the switch.
    int r;
    switch(i) {
        case 1:
            r = x + y
            cout << r;
            break;
        case 2:
            r = x - y;
            cout << r;
            break;
    };
}

其中一个好处是编译器不必在每个case块中执行本地分配(a.k.a。推入堆栈)

这种方法的一个缺点是当案例“陷入”其他情况时(即不使用break),因为变量将具有先前的值。