2013-06-18 2 views
0

От этого FAQ: What are Aggregates and PODs and how/why are they special?стручков и правила Готы

У нас есть эта часть:

Готы заявление. Как вы, возможно, знаете, это незаконно (компилятор должен выпустить ошибку), чтобы совершить переход через goto из точки, где какая-то переменная еще не была в области до точки, где она уже находится в области видимости. Это ограничение применяется только в том случае, если переменная имеет тип не-POD. В следующем примере f() плохо сформировалось, тогда как g() хорошо сформировалось. Обратите внимание, что компилятор Microsoft слишком либеральен с этим правилом - просто выдает предупреждение в обоих случаях.

int f() { 
    struct NonPOD { NonPOD(){}}; 
    goto label; 
    NonPOD x; 
label: 
    return 0; 
} 

int g(){ 
    struct POD {int i; char c;}; 
    goto label; 
    POD x; 
label: 
    return 0; 
} 

Я хотел бы понять, почему разница? Похоже, что возможно, что даже если POD , объявленный после goto, он уже инициализирован, и ничего больше не нужно делать, тогда как не-POD не инициализируется. Или я лаяю неправильное дерево?

ответ

1

Goto не может перепрыгнуть через инициализацию, если она не появится в блоке, и вы перепрыгиваете весь блок.

Для не-POD вызывается ctor. Это необходимо и должно происходить в том месте, где появляется переменная. Если вы можете перепрыгнуть через него, переменная будет доступна со сломанным состоянием. И в конечном итоге его dtor взорвет программу.

+0

Так что означает, что в случае POD инициализация уже выполнена, но в случае, отличном от POD, это не было сделано. –

+0

POD не может иметь ctor - это одно из требований. Но я думаю, что если вы использовали {} init, это тоже потерпит неудачу. –

+0

Ну, конструктор неявный и должен быть запущен в какой-то момент. Переход не может перепрыгнуть через инициализацию, поэтому POD должен быть инициализирован. Я пытаюсь выяснить, когда это произойдет. –

1

В случае f, деструктор x (который обеспечивается автоматически компилятором на основании того, конструктор, таким образом делая тип struct не-POD) будет называться «по возвращении». Вызов деструктора на объект, который не был построен, не является хорошим планом. Если мы сделаем этот код достаточно сложным, мы могли бы легко закончиться сценарием, когда компилятору очень сложно узнать, какие объекты были инициализированы, а какие нет, поэтому безопаснее просто запретить перепрыгивать через любую инициализацию (еще один общий случай это при использовании switch -statement, где некоторые объекты вводятся в каждом конкретном случае:.

switch(x) 
{ 
    case 1: 
     NonPod x; 
     .. 
     break; 
    case 2: 
     ... 
} 

является подобной конструкцией (и одинаково плохо)

+0

Итак, POD уже инициализирован, и goto может перепрыгнуть через него. Когда был инициализирован POD? –