Considérons le code suivant:
#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 ++ se plaint crosses initialization of 'int r'
. Mes questions sont:
crosses initialization
?x + y
passe la compilation, mais la dernière a échoué?crosses initialization
? ÉDITER :
Je sais que je devrais utiliser des crochets pour spécifier la portée de r
, mais je veux savoir pourquoi, par exemple, pourquoi un non-POD ne peut pas être défini dans une instruction de commutation à plusieurs cas.
Merci.
La version avec int r = x + y;
ne compilera pas non plus.
Le problème est qu'il est possible que r
atteigne la portée sans que son initialiseur ne soit exécuté. Le code se compilerait bien si vous supprimiez complètement l’initialiseur (c’est-à-dire que la ligne se lirait int r;
).
La meilleure chose à faire est de limiter la portée de la variable. De cette façon, vous satisferez à la fois 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 de manière à contourner 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 dans la portée à un point où elle est dans la portée est mal formé, sauf si la variable a le type POD (3.9) et est déclarée sans initialiseur (8.5).
Vous devriez mettre le contenu de case
entre parenthèses pour lui donner la portée, 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 Compile
cout << r;
}
break;
case 2:
...
break;
};
Il est possible de transférer dans un bloc, mais pas de manière à contourner 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 dans la portée à un point où elle est dans la portée est mal formé, sauf si la variable a le type POD et est déclarée 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 dans les blocs case
(ou le même nom de variable mais des utilisations différentes), définissez-la avant l'instruction 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;
};
}
L'un des avantages est que le compilateur n'a pas à effectuer d'allocation locale (a.k.a. En poussant sur la pile) dans chaque bloc case
.
Un inconvénient de cette approche est que les cas "tombent" dans d’autres cas (c’est-à-dire sans utiliser break
), car la variable aura une valeur antérieure.