Почему С++ обеспечивает такое поведение при инициализации крестов?

Скажем, у меня есть код С++:

if (error)
    goto exit;
... 
// size_t i = 0; //error
size_t i;
i = 0;
...
exit:
    ...

Я понимаю, что мы не должны использовать goto, но все же почему

size_t i;
i = 0;

компилируется, тогда как size_t i = 0; не работает?

Почему такое поведение соблюдается стандартом (упоминается @SingerOfTheFall)?

Можно передать в блок, но не таким образом, чтобы обходит объявления с инициализацией. Программа, которая перескакивает с где локальная переменная с автоматическим временем хранения не находится в сфера до точки, в которой она находится в сфере охвата, переменная имеет тип POD (3.9) и объявляется без инициализатора.

Ответ 1

Вы не можете перепрыгнуть через инициализацию объекта.

size_t i = 0; 

является инициализацией, а

size_t i;
i = 0;

нет. В С++ Standart говорится:

Можно передать в блок, но не таким образом, чтобы обходить объявления с инициализацией. Программа, которая перескакивает из точки, где локальная переменная с автоматической продолжительностью хранения не находится в области до точки, где она находится в области, плохо сформирована, если только переменная не имеет тип POD (3.9) и объявлена ​​без инициализатора.

Ответ 2

Причиной правила является то, что перескакивание по инициализации оставляет объект в состоянии undefined. Когда вы дойдете до конца функции, уничтожение этих неинициализированных объектов может не сработать.

Одно исключение, очевидно, что

int   i;

оставляет int неинициализированным в любом случае, поэтому пропуская это просто наполовину плохо.

Если вы хотите оставить функцию раньше, быстрый return - это вариант, чтобы избежать goto.