TL; DR
La seule façon de déclarer une variable avec un initiateur ou un objet non trivial dans un cas est d'introduire une portée de bloc en utilisant {}
ou une autre structure de contrôle qui a sa propre portée comme une boucle ou une instruction if .
Détails sanglants
Nous pouvons voir que les cas ne sont que des instructions étiquetées comme les étiquettes utilisées avec une instruction goto ( cela est couvert dans le projet de norme C ++ section 6.1 Instruction étiquetée ) et nous pouvons voir dans la section 6.7
paragraphe 3 que 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 l'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é sauf si la variable a un type scalaire, un type de classe avec un constructeur par défaut trivial et un destructeur trivial, une version qualifiée cv de l'un de ces types, ou un tableau de l'un des types précédents et est déclaré sans initialiseur (8.5).
et donne 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 une 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 valide ( exemple en direct ). Bien sûr, si vous voulez déclarer la même variable dans chaque cas, ils auront chacun besoin de leur propre portée, mais cela fonctionne de la même manière en dehors des instructions switch , donc cela ne devrait pas être une grande surprise.
En ce qui concerne la justification de ne pas autoriser le saut d'initialisation, le rapport de défaut 467, bien que couvrant un problème légèrement différent, fournit un cas raisonnable pour les variables automatiques :
[...] les variables automatiques, si elles ne sont pas explicitement initialisées, peuvent avoir des valeurs indéterminées («garbage»), y compris des représentations d'interruption, [...]
Il est probablement plus intéressant de regarder le cas où vous étendez une portée dans un basculement sur plusieurs cas, les exemples les plus célèbres de ceci sont probablement l'appareil de Duff qui ressemblerait à ceci:
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
}
}