Страницы

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

пятница, 13 марта 2020 г.

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

#cpp #компиляция #cpp11


Рассмотрим простой пример:

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.


Собственно интересует, как это реализуется во время выполнения программы.
    


Ответы

Ответ 1



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

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

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