TL;DR
La seule manière de déclarer une variable avec un initialisateur ou un objet non trivial à l'intérieur d'un fichier cas est d'introduire un portée du bloc en utilisant {}
ou une autre structure de contrôle qui a sa propre portée, comme une boucle o si la déclaration .
Détails sanglants
On peut voir que cas sont juste déclarations étiquetées comme le étiquettes utilisé avec un goto déclaration( ce sujet est traité dans le Projet de norme C++ section 6.1 Déclaration étiquetée ) et on peut voir dans la section 6.7
paragraphe 3 que le fait de sauter une déclaration n'est pas autorisé dans de nombreux cas, y compris ceux avec une initialisation :
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 87 d'un point où une variable 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ée à moins que la variable ait un type scalaire, un type classe avec un constructeur par défaut trivial et un destructeur trivial, une version qualifiée cv d'un de ces types, ou un tableau d'un des types précédents et soit déclarée sans initialisateur (8.5).
et fournit cet exemple :
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
}
Notez qu'il y a quelques subtilités ici, vous êtes autorisé à sauter au-delà d'un déclaration scalaire qui n'a pas d'initialisation, par exemple :
switch( n )
{
int x ;
//int x = 10 ;
case 0:
x = 0 ;
break;
case 1:
x = 1 ;
break;
default:
x = 100 ;
break ;
}
est parfaitement valable( exemple concret ). Bien sûr, si vous voulez déclarer la même variable dans chaque cas alors ils auront chacun besoin de leur propre champ d'application, mais cela fonctionne de la même manière en dehors de l'application commutateur également, ce qui ne devrait pas être une grande surprise.
Quant à la raison pour laquelle on ne permet pas le saut après l'initialisation, rapport de défaut 467 bien que couvrant une question légèrement différente, fournit un cas raisonnable pour variables automatiques :
[...] les variables automatiques, si elles ne sont pas explicitement initialisées, peuvent avoir des valeurs indéterminées ("garbage"), y compris les représentations de pièges, [...]
Il est probablement plus intéressant de se pencher sur le cas où vous étendez une portée à l'intérieur d'un fichier commutateur sur plusieurs cas l'exemple le plus célèbre est probablement Dispositif de Duff qui ressemblerait à quelque chose comme ça :
void send( int *to, const int *from, int count)
{
int n = (count + 7) / 8;
switch(count % 8)
{
case 0: do { *to = *from++; // <- Scope start
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while(--n > 0); // <- Scope end
}
}
58 votes
Une utilisation peut consister à limiter la portée des variables déclarées dans l'instruction case.
3 votes
stackoverflow.com/questions/92396/
1 votes
Trop d'indentations, aussi. Les cas ne sont que des étiquettes à l'intérieur du bloc de l'instruction switch : ils n'introduisent pas d'imbrication supplémentaire, ils devraient donc s'aligner sur le bloc de l'instruction switch.
switch
et, dans le deuxième exemple, les déclarations incluses ne sont indentées qu'une seule fois. Notez que vous avez un désindentation maladroite de quatre espaces après le mot-clébreak;
.0 votes
Remarque, la réponse acceptée n'est que partiellement correcte car Commentaire de Jack souligne et manque certaines subtilités, que j'aborde dans ma réponse.
0 votes
Juste pour info : en C (même C11) plutôt qu'en C++, vous ne pouvez pas étiqueter une déclaration ; elles ne sont pas dans la catégorie syntaxique
statement
. En C++, vous pouvez (un composant de la catégorie syntaxiquestatement
esdeclaration statement
).