可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Consider following code:
#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++ complains crosses initialization of 'int r'
.My questions are:
- What is
crosses initialization
? - Why do the first initializer
x + y
pass the compilation,but the later failed? - What are the problems of so-called
crosses initialization
?
EDIT:
I know I should use brackets to specify the scope of r
but I want to know why,for example why non-POD could not be defined in multi-case switch statement.
Thanks.
回答1:
The version with int r = x + y;
won't compile either.
The problem is that it is possible for r
to come to scope without its initializer being executed. The code would compile fine if you removed the initializer completely (i.e. the line would read int r;
).
The best thing you can do is to limit the scope of the variable. That way you'll satisfy both the compiler and the reader.
switch(i) { case 1: { int r = 1; cout << r; } break; case 2: { int r = x - y; cout << r; } break; };
The Standard says (6.7/3):
It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A program that jumps from a point where a local variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has POD type (3.9) and is declared without an initializer (8.5).
回答2:
You should put the contents of the case
in brackets to give it scope, that way you can declare local variables inside it:
switch(i) { case 1: { // int r = x + y; -- OK int r = 1; // Failed to Compile cout << r; } break; case 2: ... break; };
回答3:
It is possible to transfer into a block, but not in a way that bypasses declarations with initialization. A program that jumps from a point where a local variable with automatic storage duration is not in scope to a point where it is in scope is ill-formed unless the variable has POD type and is declared without an initializer.
[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]
The transfer from the condition of a switch statement to a case label is considered a jump in this respect.
回答4:
I suggest you promote your r
variable before the switch
statement. If you want to use a variable across the case
blocks, (or the same variable name but different usages), define it before the switch statement:
#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; }; }
One of the benefits is that the compiler does not have to perform local allocation (a.k.a. pushing onto the stack) in each case
block.
A drawback to this approach is when cases "fall" into other cases (i.e. without using break
), as the variable will have a previous value.