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

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

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

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

4 ответа

Решение

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

Параграф 2:

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

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

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

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

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

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

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

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

C++ 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
}

- конец примера]

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

Проще говоря... start: является меткой и объявляет [другую область]

Если предположить, start как есть <0x00003000>А будет в <0x00003000> + some_offset сказать <0x00003004>,

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

Другие вопросы по тегам