Я запустил пример программы, и действительно вызываются деструкторы для объектов, выделенных стеком, но гарантируется ли это стандартом?
Вызываются ли деструкторы после броска в C ++?
Ответы (3)
Да, это гарантировано (при условии, что исключение перехвачено), вплоть до порядка, в котором вызываются деструкторы:
C ++ 11 15.2 Конструкторы и деструкторы [except.ctor]
1 Когда управление переходит от выражения throw к обработчику, деструкторы вызываются для всех автоматических объектов, созданных с момента входа в блок 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 () [except.terminate]
2 В ситуации, когда соответствующий обработчик не найден, определяется реализацией, будет ли развернут стек перед вызовом
std::terminate()
.
Да, деструкторы гарантированно будут вызываться при раскручивании стека, в том числе при раскручивании из-за возникшего исключения. Есть лишь несколько приемов, за исключением которых вы должны запомнить:
- Деструктор класса не вызывается, если в его конструкторе возникло исключение.
- Исключение автоматически генерируется повторно, если оно попадает в блок catch списка инициализации конструкции.
terminate()
будет вашим процессом. Мне было бы интересно увидеть контрпримеры ...
- person DevSolar; 29.11.2011
release
.
- person Cheers and hth. - Alf; 29.11.2011
try
в деструкторе). Visual C ++ никогда не реализовывал стандартную функцию для проверки, и эта функция в любом случае неадекватна. так что это немного проблематично, но не полная демонстрация, поскольку код использования может быть разработан вокруг этого.
- person Cheers and hth. - Alf; 29.11.2011
Если перехватывается throw, обычно операции cpp продолжаются. Это включает деструкторы и выталкивание стека. Однако, если исключение не обнаружено, выталкивание стека не гарантируется.
Также мой мобильный компилятор не может поймать пустой бросок или пустой бросок.
пример:
#include <Jav/report.h>
int main()
{
try { throw; }
catch(...) { rep("I bet this is not caught"); }
}