В стандарте проводится различие между двумя формами уничтожения, которые возникают при возникновении исключения. Акцент на мой.
§15.2/1
Поскольку управление переходит из выражения throw в обработчик, деструкторы вызывают для всех автоматических объектов построенный с момента ввода блока try. Автоматические объекты уничтожаются в обратном порядке завершение их строительства.
§15.2/2
Объект любой продолжительности хранения, инициализация или уничтожение которого заканчивается исключением, будет имеют деструкторы, выполняемые для всех своих полностью построенных подобъектов (исключая варианты элементов класс объединения), т.е. для подобъектов, для которых главный конструктор (12.6.2) завершил выполнение и деструктор еще не приступил к исполнению. Аналогично, если конструктор без делегирования для объекта завершил выполнение, и конструктор делегирования для этого объекта завершает исключение, объекты деструктор будет вызван. Если объект был выделен в новом выражении, соответствующее освобождение функция (3.7.4.2, 5.3.4, 12.5), если она есть, вызывается для освобождения памяти, занимаемой объектом.
§15.2/3
Процесс вызова деструкторов для автоматических объектов, построенных по пути от блока try к throw-expression называется "разворачивание стека". Если деструктор, вызванный во время разматывания стека, выходит с исключение,
std::terminate
называется (15.5.1). [Примечание: деструкторы, как правило, поймают исключения и не позволяйте им распространяться из деструктора. - конечная нота]
Итак, кажется, что мы имеем (a) раскрутку стека, которая разрушает автоматические объекты, и (b) уничтожение полностью построенных подобъектов объекта, конструктор или деструктор которого выходит из исключения, что происходит независимо от продолжительности хранения.
В осторожном чтении в § 15.2/1 предполагается, что разворачивание стека обязательно обязательно происходит, если управление переходит к обработчику, оставляя открытым возможность того, что удаление строк может не произойти, если исключение не обрабатывается. Действительно, в §15.5.2/2 говорится:
В ситуации, когда никакой обработчик соответствия не найден, он определяется реализацией независимо от того, разрывается ли стек до того, как вызывается
std::terminate()
.
Но формулировка § 15.2/2, похоже, не оставляет открытой такой возможности. Он просто говорит, что инициализация или уничтожение должны быть прекращены за счет исключения - не то, что контроль должен пройти к обработчику. Поэтому моя интерпретация заключается в том, что даже если исключение не обрабатывается, подобъекты все еще уничтожаются. Это правильная интерпретация?
Например, допустим, что
std::vector<int> V;
ComplicatedObject* p = new ComplicatedObject();
и ComplicatedObject
вызывает конструктор, и исключение не обрабатывается. Затем уничтожается ли V
, определяется ли реализация. Является ли также определением реализации, уничтожены ли полностью построенные подобъекты *p
? Обратите внимание, что такие объекты не имеют автоматической продолжительности хранения.