什么是十字架初始化的迹象?
考虑下面的代码:
#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'
我的问题是:
- 什么是
crosses initialization
? - 为什么第一个初始化函数
x + y
通过编译,但后来失败? - 所谓的
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
语句之前提升你的r
variables。 如果你想要在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将有一个先前的价值。