Страницы

Поиск по вопросам

воскресенье, 2 июня 2019 г.

Каким образом определяется необходимость вызова деструктора для объектов с автоматической продолжительностью хранения?

Рассмотрим простой пример:
void f(); void f_exception();
class A { private: std::string m_name;
public: A(std::string name) : m_name(name) {/*NOP*/}
~A() { std::cout << "Destroy object \"" << m_name << "\"." << std::endl; } };
int main() { f();
try { f_exception(); } catch (const std::runtime_error& e) { std::cout << "Catch exception." << std::endl; }
return 0; }
void f() { A a("a");
std::cout << "Before block" << std::endl; { A b("b"); } std::cout << "After block." << std::endl; }
void f_exception() { A c("c");
std::cout << "Before block" << std::endl; { A d("d"); throw std::runtime_error("exception"); } }
Стандарт гарантирует, что объекты с automatic storage duration будут удалены при выходе из блока кода, в котором они объявлены. Я предположил, что при компиляции создаются соответствующие инструкции, но ведь выход из блока может быть осуществлен и ранее (при использовании исключений, оператора goto, оператора return и т.д.). Т.е. необходимость вызова деструктора должна определяться динамически при выполнении программы. Это и подтверждает приведенный выше пример (вывод в консоль):
Before block Destroy object "b". After block. Destroy object "a". Before block Destroy object "d". Destroy object "c". Catch exception.
Собственно интересует, как это реализуется во время выполнения программы.


Ответ

Почему динамически? Все инструкции известны компилятору, а это значит что он для всякой инструкции, которая ведёт к «покиданию» текущей области может добавить вызов деструктора(ов). Здесь нет никакой магии, и не требуется анализа рантайма — просто работа для компилятора.
Кстати, вот это:
Стандарт гарантирует, что объекты с automatic storage duration будут удалены при выходе из блока кода, в котором они объявлены.
Не совсем правда. Попробуйте написать exit(0) в коде — Вы не увидите ни одного деструктора или попробуйте добавить noexcept к функции f_exception() — будет похожий результат.

Комментариев нет:

Отправить комментарий