Подтвердить что ты не робот

Почему деструктор вызывается при движении назад через goto

Возможный дубликат:
Будет ли использовать переменные утечки goto?

В следующем примере, когда goto вызывается для перехода "назад", вызывается деструктор A. Почему так? Объект A не оставляет своей области, не так ли? Стандарт ли что-нибудь говорит об этом поведении в отношении goto?

void f()
{
start:
    A a;
    goto start;
}
4b9b3361

Ответ 1

6.6 Операторы перехода [stmt.jump]

Пункт 2:

При выходе из области действия (как бы это ни было сделано) объекты с автоматической продолжительностью хранения (3.7.3), которые были построены в этой области, уничтожаются в обратном порядке их построения. [Примечание: для временных, см. 12.2. -end note] Передача из цикла, из блока, или обратно после инициализированной переменной с автоматическим временем хранения включает в себя уничтожение объектов с автоматическим временем хранения, которые находятся в области в точке, переданной из но не в точке, переведенной на. (См. 6.7 для передачи в блоки). [Примечание. Однако программа может быть завершена (например, путем вызова std:: exit() или std:: abort() (18.5)), не уничтожая объекты класса с автоматическим временем хранения. - конечная нота]

Я думаю, что важная часть:

или обратно за инициализированную переменную с автоматическим временем хранения включает уничтожение

Ответ 2

Время жизни объекта a начинается с его объявления и продолжается до конца блока, содержащего его.

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

  • point of declaration для имени сразу после его полного объявления (раздел 8) и перед его инициализатором (если есть), [...] (п. 3.3.2)

  • Имя, объявленное в блоке (6.3), является локальным для этого блока; он имеет блокировку. Его потенциальный объем начинается с (3.3.2) и заканчивается в конце его блока. Переменная, объявленная в области блока, является локальной переменная. (П. 3.3.3)

Ответ 3

Вот соответствующая цитата из стандарта. Он даже включает пример, который почти идентичен вашему:

С++ 11 6.7 Декларация о заявлении [stmt.dcl]

2 Переменные с автоматическим временем хранения (3.7.3) инициализируются каждый раз, когда их выражение-выражение казнены. Переменные с автоматическим временем хранения, объявленным в блоке, уничтожаются при выходе из блок (6.6).

3 Можно передать в блок, но не таким образом, чтобы обходить объявления с инициализацией. программа, которая перескакивает с точки, где переменная с автоматической продолжительностью хранения не имеет точка, где она находится в области видимости, плохо сформирована, если переменная не имеет скалярного типа, тип класса с тривиальным значением по умолчанию конструктор и тривиальный деструктор, 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
}

-end пример]

Как объясняется в примере, goto подразумевает разрушение. Объявление-выражение (A a; в вашем коде) означает, что конструктор повторно выполняется после каждого перехода.

Ответ 4

Проще говоря... start: - это метка и объявляет область [ноль]

Предполагая, что start равно <0x00003000>, A a будет в <0x00003000> + some_offset сказать <0x00003004>.

goto start попросит ПК (счетчик программ) перейти к адресу запуска, который возникает перед объявлением A - вне его области действия - следовательно, "destroy a" вызывает деструктор.