Условная инициализация в коммутаторе
почему этот фрагмент кода работает нормально
void foo(int i)
{
switch(i) {
case 1:
{
X x1;
break;
}
case 2:
X x2;
break;
}
}
в то время как следующее дает ошибку компиляции (инициализация " x1 "пропускается меткой "case")?
void foo(int i)
{
switch(i) {
case 1:
X x1;
break;
case 2:
X x2;
break;
}
}
Я понимаю, что использование фигурных скобок вводит новую область, поэтому хранилище не будет выделено для x1, пока мы не нажмем его открывающую скобку. Но x2 по-прежнему инициализируется внутри метки случая, не заключая фигурные скобки. Не должно ли это быть ошибкой?
Я думаю, что инициализация x2 может быть условно пропущены оба фрагмента кода
5 ответов
1: допустимый
case 1:
{
X x1;
break;
}
если он не попадает в условие,x1
не может использоваться никакими дальнейшими утверждениями, поэтому не может быть ошибки во время выполнения с этим. x1
не пытается существовать вне скобок.
2: неверный
switch(i) {
case 1:
X x1; //don't break
i = 2;
...
...
...
case 2:
x1.someOperation()
}
в приведенном выше, если i
был 2
первоначально вы нажмете x1.someOperation()
до X x1
который построил бы объект.
если был разрешено компилировать, это приведет к ошибке выполнения или нет, в зависимости от того, является ли случае:1 был выполнен до 2, (и объект был построен). Следовательно, компилятор запрещает его.
то же самое разрешено с обычными старыми типами данных, которые не может есть пользовательский конструктор.
обратите внимание, что вы получите ошибку только тогда, когда X
- Это не-Pod. Если X
Это POD, тогда вы не получите никакой ошибки (когда вы не используете фигурные скобки).
в случае не-стручка, вы не может пропустить инициализацию переменных, объявленных в той же области. Это приводит к ошибке компиляции, когда вы не используете скобки, потому что switch
позволяет пропустить инициализация переменных, но в то же время это сделало их доступными для использования в все case
надписи под ним. Это опасно.
подумайте об этом: если i
is 2
, то управление будет прыгать на второй case
напрямую без инициализации x1
, и тогда вы сможете использовать x1
во втором случае, даже если он не инициализирован. Это не имеет смысла. Поэтому язык требует, чтобы это была ошибка.
кстати, чтобы узнать, что такое POD и non-POD, см. Эти темы:
общая идея заключается в том, что каждый case
не является изолированной областью: код под case 2
может относиться к x1
переменная, так как она была объявлена ранее в той же области (т. е.: весь switch
block): Конечно, он не был бы инициализирован, и это привело бы к ошибке.
добавление фигурных скобок вы фактически разделяете каждый case
область, позволяющая объявлять переменные в case 1
это не может быть отнесено вне его.
не рекомендуется создавать переменные внутри условных операторов. Я рекомендую вам создать переменную вне switch
оператор, а затем asign значения к нему в соответствии с условием на i
:
void foo(int i) {
X x1;
switch(i) {
case 1:
x1 = ...;
break;
case 2:
x1 = ...;
break;
}
}
в версии, которая терпит неудачу, объявление x1
не выйдут из области видимости до нескольких строк после case 2:
метки. Вот в чем проблема. Заявление x2
нормально, потому что нет case
метка между объявлением и концом его области действия.