Почему деструктор вызывается при движении назад через goto
Возможный дубликат:
Будет ли использовать переменные утечки goto
?
В следующем примере, когда goto
вызывается для перехода "назад", вызывается деструктор A
. Почему так? Объект A
не оставляет своей области, не так ли? Стандарт ли что-нибудь говорит об этом поведении в отношении goto
?
void f()
{
start:
A a;
goto start;
}
Ответы
Ответ 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
" вызывает деструктор.