TL; DR
L'unico modo per dichiarare una variabile con un inizializzatore o un oggetto non banale all'interno di un case è introdurre uno scope di blocco usando {}
o un'altra struttura di controllo che abbia il proprio ambito come un ciclo o un'istruzione if .
Dettagli cruenti
Possiamo vedere che i casi sono solo istruzioni etichettate come le etichette usate con un'istruzione goto ( questo è trattato nella bozza di C ++ sezione 6.1 Dichiarazione etichettata ) e possiamo vedere dalla sezione 6.7
paragrafo 3 che saltare una dichiarazione non è consentito in molti casi , compresi quelli con un'inizializzazione:
È possibile trasferire in un blocco, ma non in un modo che aggiri le dichiarazioni con inizializzazione. Un programma che salta 87 da un punto in cui una variabile con durata di memorizzazione automatica non è nell'ambito a un punto in cui è nell'ambito è mal formato a meno che la variabile non abbia un tipo scalare, un tipo di classe con un banale costruttore predefinito e un banale distruttore, una versione qualificata da cv di uno di questi tipi o un array di uno dei tipi precedenti e viene dichiarata senza un inizializzatore (8.5).
e fornisce questo esempio:
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
}
Nota, ci sono alcune sottigliezze qui, puoi saltare oltre una dichiarazione scalare che non ha un'inizializzazione, ad esempio:
switch( n )
{
int x ;
//int x = 10 ;
case 0:
x = 0 ;
break;
case 1:
x = 1 ;
break;
default:
x = 100 ;
break ;
}
è perfettamente valido ( esempio dal vivo ). Ovviamente se vuoi dichiarare la stessa variabile in ogni caso, ognuno di loro avrà bisogno del proprio ambito, ma funziona allo stesso modo anche al di fuori delle istruzioni switch , quindi non dovrebbe essere una grande sorpresa.
Per quanto riguarda la logica per non consentire l'inizializzazione del salto passato, il report di difetto 467, sebbene copra un problema leggermente diverso, fornisce un caso ragionevole per le variabili automatiche :
le variabili [...] automatiche, se non esplicitamente inizializzate, possono avere valori indeterminati ("garbage"), incluse rappresentazioni trap, [...]
Probabilmente è più interessante osservare il caso in cui estendi un ambito all'interno di uno switch su più casi, gli esempi più famosi di questo è probabilmente il dispositivo di Duff che sarebbe simile a questo:
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
}
}