什么是十字架初始化的迹象?

考虑下面的代码:

#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什么问题?

编辑
我知道我应该使用括号来指定r的范围,但是我想知道为什么,例如,为什么non-POD不能在多个case switch语句中定义。

谢谢。

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

问题在于r可能没有执行初始化程序就可以进入范围。 如果你完全删除了初始化程序,代码会很好地编译(即行将读取int r; )。

你可以做的最好的事情是限制variables的范围。 这样你就可以同时满足编译器和读者。

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

标准说(6.7 / 3):

可以将其转换为块,但不能以绕过具有初始化的声明的方式。 从具有自动存储持续时间的局部variables不在范围内的点跳转到在范围内的点跳转的程序是格式不正确的,除非variables具有PODtypes(3.9),并且没有使用初始值设定项(8.5)进行声明。

你应该把括号中的内容给它的范围,这样你可以在其中声明局部variables:

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

可以将其转换为块,但不能以绕过具有初始化的声明的方式。 从具有自动存储持续时间的本地variables不在范围内的点跳转到在范围内的点跳转的程序是格式错误的,除非variables具有PODtypes并且没有初始化程序而声明。

 [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标签在这方面被认为是一个跳跃。

我build议你在switch语句之前提升你的rvariables。 如果你想要在case块之间使用一个variables(或者是相同的variables名,但是不同的用法),那么在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; }; } 

其中一个好处是,编译器不必在每个大块中执行本地分配(也就是推入堆栈)

这种方法的缺点是当案件“落入”其他案件(即不使用break ),因为variables将有一个先前的价值。