TL; DR
Единственный способ объявить переменную с инициализатором или каким-либо нетривиальным объектом внутри кейса - это ввести область видимости блока, используя {}
или другую структуру управления, которая имеет собственную область видимости, такую как цикл или оператор if .
Кровавые подробности
Мы можем видеть, что кейсы - это просто помеченные операторы, такие как метки, используемые с оператором goto ( это описано в разделе 6.1 проекта стандарта C ++ с пометкой ), и мы можем видеть из 6.7
параграфа 3 раздела, что переход объявления во многих случаях не допускается , в том числе с инициализацией:
Возможен переход в блок, но не в обход объявлений с инициализацией. Программа, которая перескакивает на 87 из точки, где переменная с автоматической продолжительностью хранения не находится в области видимости, к точке, где она находится в области видимости, плохо сформирована, если только переменная не имеет скалярный тип, тип класса с тривиальным конструктором по умолчанию и тривиальным деструктором, квалифицированная cv версия одного из этих типов или массив одного из предыдущих типов и объявляется без инициализатора (8.5).
и предоставляет этот пример:
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
}
Обратите внимание, здесь есть некоторые тонкости, вы можете пропустить скалярное объявление , не имеющее инициализации, например:
switch( n )
{
int x ;
//int x = 10 ;
case 0:
x = 0 ;
break;
case 1:
x = 1 ;
break;
default:
x = 100 ;
break ;
}
совершенно верно ( живой пример ). Конечно, если вы хотите объявить одну и ту же переменную в каждом случае, тогда каждому из них понадобится своя область видимости, но это работает так же, как и вне переключателя. операторов , так что это не должно быть большим сюрпризом.
Что касается обоснования запрета перехода после инициализации, отчет 467 о дефекте, хотя и охватывает несколько иную проблему, представляет собой разумный случай для автоматических переменных :
[...] автоматические переменные, если они не инициализированы явно, могут иметь неопределенные («мусорные») значения, включая представления ловушек, [...]
Вероятно, более интересно взглянуть на случай, когда вы расширяете область действия в рамках переключателя на несколько случаев, наиболее известным примером этого, вероятно, является устройство Даффа, которое будет выглядеть примерно так:
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
}
}