What are the signs of crosses initialization?

匿名 (未验证) 提交于 2019-12-03 02:11:02

问题:

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:

  1. What is crosses initialization?
  2. Why do the first initializer x + y pass the compilation,but the later failed?
  3. 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.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!