С++: почему мы можем объявить переменную в случае переключения

int i;
i = 2;
switch(i)
{
    case 1: 
        int k;
        break;
    case 2:
        k = 1;
        cout<<k<<endl;
        break;
}

Я не знаю, почему работает код выше.

Здесь мы никогда не можем перейти к случаю 1, но почему мы можем использовать k в случае 2?

Ответ 1

На самом деле есть 2 вопроса:

1. Почему я могу объявить переменную после метки case?

Это потому, что в С++ метка должна быть в форме:

N3337 6.1/1

меченый-оператор:

...

  • атрибут-спецификатор-seqopt case constant-expression: statement

...

И в заявлении объявления C++ также рассматривается как оператор (в отличие от C):

N3337 6/1:

утверждение:

...

  • декларация-выражение

...

2. Почему я могу перейти через объявление переменной, а затем использовать его?

Потому что: N3337 6.7/3

Можно передать в блок , но не таким образом, чтобы обходить объявления с инициализацией. программа, которая прыгает ( передача из условия оператора оператора на ярлык case рассматривается как прыжок в этом отношении.)

из точки, где переменная с продолжительностью автоматического хранения не находится в области до точки, где она находится в области, неформатирована , если переменная не имеет скалярный тип тип класса с тривиальным значением по умолчанию конструктор и тривиальный деструктор, cv-квалифицированная версия одного из этих типов или массив одного из предшествующих типов и объявляется без инициализатора (8.5).

Так как k имеет скалярный тип и не инициализируется в точке объявления, прыгающей через него, то объявление возможно. Это семантически эквивалентно:

goto label;

int x;

label:
cout << x << endl;

Однако это не сработает, если x был инициализирован в точке объявления:

 goto label;

    int x = 58; //error, jumping over declaration with initialization

    label:
    cout << x << endl;