Quels sont les signes d’initialisation des croix?

Considérez le code suivant:

#include  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 Comstack cout << r; break; case 2: r = x - y; cout << r; break; }; } 

G ++ se plaint d’une crosses initialization of 'int r' Mes questions sont:

  1. Qu’est-ce que l’ crosses initialization ?
  2. Pourquoi le premier initialiseur x + y réussit-il la compilation, mais la dernière a échoué?
  3. Quels sont les problèmes d’ crosses initialization ?

EDIT :
Je sais que je devrais utiliser des parenthèses pour spécifier la scope de r mais je veux savoir pourquoi, par exemple pourquoi la non-POD n’a pas pu être définie dans l’instruction de changement multi-casse.

Merci.

La version avec int r = x + y; ne comstackra pas non plus.

Le problème est qu’il est possible que r intervienne sans que son initialiseur ne soit exécuté. Le code comstackrait bien si vous supprimiez complètement l’initialiseur (c.-à-d. Que la ligne lirait int r; ).

La meilleure chose à faire est de limiter la scope de la variable. De cette façon, vous satisferez le compilateur et le lecteur.

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

La norme dit (6.7 / 3):

Il est possible de transférer dans un bloc, mais pas d'une manière qui contourne les déclarations avec initialisation. Un programme qui saute d'un point où une variable locale avec une durée de stockage automatique n'est pas à scope est mal formé à moins que la variable ait le type POD (3.9) et soit déclaré sans initialiseur (8.5).

Vous devez mettre le contenu de la case entre parenthèses pour lui donner une scope, de cette façon vous pouvez déclarer des variables locales à l’intérieur:

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

Il est possible de transférer dans un bloc, mais pas d’une manière qui contourne les déclarations avec initialisation. Un programme qui saute d’un point où une variable locale avec une durée de stockage automatique n’est pas à scope est mal formé à moins que la variable ait le type POD et soit déclaré sans initialiseur.

 [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] 

Le transfert de la condition d’une instruction switch à une étiquette de cas est considéré comme un saut à cet égard.

Je vous suggère de promouvoir votre variable r avant l’instruction switch . Si vous souhaitez utiliser une variable à travers les blocs de case (ou le même nom de variable mais des utilisations différentes), définissez-la avant l’instruction switch:

 #include  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; }; } 

L’un des avantages est que le compilateur n’a pas à effectuer d’allocation locale (c’est-à-dire à pousser sur la stack) dans chaque bloc de case .

Un inconvénient de cette approche réside dans le fait que les cas «tombent» dans d’autres cas (c’est-à-dire sans utiliser de break ), car la variable aura une valeur précédente.