Давайте посмотрим на этот фрагмент кода:
#include <iostream>
#include <stdexcept>
class A {
public:
A() {
std::cout << "A's constructor\n";
}
~A() {
std::cout << "A's destructor\n";
}
};
class B {
public:
B() {
std::cout << "B's constructor - begin\n";
throw std::runtime_error("Error");
std::cout << "B's constructor - end\n";
}
~B() {
std::cout << "B's destructor\n";
}
private:
A a;
};
int main() {
try {
B b;
} catch(const std::runtime_error& exc) {
std::cerr << exc.what() << '\n';
}
}
Вот вывод программы:
A's constructor
B's constructor - begin
A's destructor
Error
В общем, когда объект создается сначала, его конструкторы его полей вызываются, а затемконструктор для объекта выполнен.Для каждого успешно выполненного конструктора должен быть вызван деструктор.Деструкторы вызываются в обратном порядке.Если конструктор дает сбой, тогда не вызывается деструктор, но если во время конструирования объекта некоторые или все его поля конструируются, они будут уничтожены.
Возвращаясь к примеру, в созданной мной функции main
объект класса B
.Объект содержит член класса A
.Когда объект b
создан, сначала создаются его поля (в данном случае это элемент с именем a
) - это первая строка вывода.Затем конструктор объекта b
начинает выполнение (вторая строка вывода).Конструктор B
вызывает исключение.Поскольку конструктор поля b
(то есть конструктор a
) уже успешно выполнен, деструктор a
должен называться - третья строка вывода.Теперь конструктор b
не успешно завершил свое выполнение, поэтому деструктор не будет вызываться для b
.Последняя строка вывода - это результат обработки кода исключением в функции main
.
В этом примере вы можете видеть, что когда конструктор завершается успешно, через некоторое время вызывается соответствующий деструктор.Однако, если конструктор терпит неудачу, деструктор для объекта не будет вызван.
Успешно выполненные конструкторы и деструкторы всегда связаны.Это очень общее правило, и оно справедливо также для базовых классов (если они есть), объектов, размещенных в массивах, объектов, размещенных в стеке и т. Д. - даже очень странные и сложные случаи всегда обрабатываются таким образом.