TL; DR
Die einzige Möglichkeit, eine Variable mit einem Intializer oder einem nicht trivialen Objekt in einem Fall zu deklarieren, besteht darin, einen Blockbereich mithilfe einer {}
anderen Steuerungsstruktur einzuführen, die einen eigenen Bereich wie eine Schleife oder eine if-Anweisung hat .
Gory Details
Wir können sehen, dass Fälle nur beschriftete Anweisungen sind, wie die Beschriftungen, die mit einer goto- Anweisung verwendet werden ( dies wird im C ++ - Entwurf des Standardabschnitts 6.1 Beschriftete Anweisung behandelt ), und wir können aus Abschnitt 6.7
Absatz 3 ersehen, dass das Überspringen einer Deklaration in vielen Fällen nicht zulässig ist , einschließlich solcher mit einer Initialisierung:
Es ist möglich, in einen Block zu übertragen, jedoch nicht so, dass Deklarationen bei der Initialisierung umgangen werden. Ein Programm , das springt 87 von einem Punkt , wo eine Variable mit einer Dauer dynamischer Speichers ist in ihrem Umfang nicht bis zu einem Punkt , wo sie in ihrem Umfang ist schlecht gebildet , wenn die variable skalare Typen hat, Klassentyp mit einer trivialen Standardkonstruktors und einem trivialen destructor, eine cv-qualifizierte Version eines dieser Typen oder ein Array eines der vorhergehenden Typen und wird ohne Initialisierer deklariert (8.5).
und bietet dieses Beispiel:
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
}
Beachten Sie, dass es hier einige Feinheiten gibt. Sie können an einer Skalardeklaration vorbei springen , die keine Initialisierung hat, zum Beispiel:
switch( n )
{
int x ;
//int x = 10 ;
case 0:
x = 0 ;
break;
case 1:
x = 1 ;
break;
default:
x = 100 ;
break ;
}
ist vollkommen gültig ( Live-Beispiel ). Wenn Sie in jedem Fall dieselbe Variable deklarieren möchten, benötigen sie natürlich jeweils einen eigenen Gültigkeitsbereich, aber dies funktioniert auch außerhalb von switch- Anweisungen auf dieselbe Weise. Dies sollte also keine große Überraschung sein.
In Bezug auf die Gründe, warum ein Sprung nach der Initialisierung nicht zulässig ist, liefert der Fehlerbericht 467, obwohl er ein etwas anderes Problem abdeckt, einen vernünftigen Fall für automatische Variablen :
[...] automatische Variablen können, wenn sie nicht explizit initialisiert werden, unbestimmte ("Müll") Werte haben, einschließlich Trap-Darstellungen, [...]
Es ist wahrscheinlich interessanter, den Fall zu betrachten, in dem Sie einen Bereich innerhalb eines Switches auf mehrere Fälle erweitern. Das bekannteste Beispiel hierfür ist wahrscheinlich Duffs Gerät, das ungefähr so aussehen würde:
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
}
}