Деструкторы вызываются после броска в C ++? - PullRequest
41 голосов
/ 29 ноября 2011

Я запустил пример программы и действительно вызывались деструкторы для объектов, выделенных стеком, но гарантируется ли это стандартом?

Ответы [ 3 ]

56 голосов
/ 29 ноября 2011

Да, это гарантировано (при условии, что исключение перехвачено), вплоть до порядка , в котором вызываются деструкторы:

C ++ 11 15,2Конструкторы и деструкторы [исключением.ктор]

1 Когда управление переходит от выражения-броска к обработчику, деструкторы вызываются для всех автоматических объектов, созданных с момента ввода блока try.Автоматические объекты уничтожаются в порядке, обратном завершению их построения.

Кроме того, если исключение выдается при построении объекта, подобъекты частично построенного объекта гарантированно будут правильно уничтожены.:

2 У объекта любой продолжительности хранения, инициализация или уничтожение которого завершается исключением, будут деструкторы, выполняемые для всех его полностью построенных подобъектов (исключая вариантные члены класса, подобного объединению),то есть для подобъектов, для которых главный конструктор (12.6.2) завершил выполнение, а деструктор еще не начал выполнение.Аналогично, если не делегирующий конструктор для объекта завершил выполнение и делегирующий конструктор для этого объекта завершается с исключением, будет вызван деструктор объекта.Если объект был выделен в новом выражении, соответствующая функция освобождения (3.7.4.2, 5.3.4, 12.5), если таковая имеется, вызывается для освобождения памяти, занятой объектом.

Весь этот процесс известен как «разматывание стека»:

3 Процесс вызова деструкторов для автоматических объектов, созданных на пути от блока try к выражению throw, называется «разматывание стека». Еслидеструктор, вызываемый при разматывании стека, выходит с исключением, вызывается std :: terminate (15.5.1).

Разматывание стека составляет основу широко используемой методики Инициализация (RAII) .

Обратите внимание, что разматывание стека не обязательно выполняется, если исключение не перехвачено.В этом случае выполнение развертывания стека зависит от реализации.Но независимо от того, выполняется разматывание стека или нет, в этом случае вам гарантирован окончательный вызов std::terminate.

C ++ 11 15.5.1. Std :: terminate ()функция [исключением. завершить]

2… В ситуации, когда соответствующий обработчик не найден, определяется реализацией, будет ли стек разматываться перед вызовом std::terminate().

6 голосов
/ 29 ноября 2011

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

  • Деструктор класса не вызывается, если в его конструктор выдается исключение.
  • Исключение автоматически перебрасывается, если перехватывается в блоке перехвата списка инициализации конструкции.
0 голосов
/ 19 июня 2019

Если бросок пойман, то обычно операции cpp продолжаются.Это включает в себя деструкторы и выталкивание стека.Однако, если исключение не перехвачено, выталкивание стека не гарантируется.

Мой мобильный компилятор также не может обработать голый или пустой бросок.

пример:

#include <Jav/report.h>

int main()
{
 try { throw; }
 catch(...) { rep("I bet this is not caught"); }
 }
...