Деструктор


Деструктор выполняет освобождение использованных объектом ресурсов и удаление нестатических переменных объекта. По сути деструктор - это функция, которая называется по имени класса (как и конструктор) и перед которой стоит тильда (~). Деструктор не имеет возвращаемого значения и не принимает параметров. Каждый класс может иметь только один деструктор.

Деструктор автоматически вызывается, когда удаляется объект. Удаление объекта происходит в следующих случаях:

когда завершается выполнение области видимости, внутри которой определены объекты

когда удаляется контейнер (например, массив), который содержит объекты

когда удаляется объект, в котором определены переменные, представляющие другие объекты

динамически созданные объекты удаляются при применении к указателю на объект оператора delete

Рассмотрим следующую ситуацию:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <string>

class Person
{
public:
Person(std::string n)
{
name = n;
}
~Person()
{
std::cout << "Destructor called for Person " << name << std::endl;
}
private:
std::string name;
};
int main()
{
Person tom("Tom");
Person *sam = new Person("Sam");
delete sam; // вызывается деструктор для объекта sam
std::cout << "End of Main" << std::endl;
return 0;
} // вызывается деструктор для объекта tom
В классе Person определен деструктор:

1
2
3
4
~Person()
{
std::cout << "Destructor called for Person " << name << std::endl;
}
Все, что делает данный деструктор, это выводит на консоль соответствующее сообщение. Как правило, деструкторы определяют код для особождения ресурсов, но в данном случае нам не надо освобождать никаких ресурсов, и мы могли бы определить даже пустой деструктор.

В функции main создается переменная tom, которая хранит объект Person. Это обычная переменная, не указатель. И для нее деструктор будет вызываться, когда завершит выполнение та область видимости, где эта переменная определена, то есть функция main.

Также здесь определен указатель bob, который указывает на объект Person. Это динамический объект, который определяется с помощью ключевого слова new. Когда такие объекты выходят из области видимости, то для них автоматически не выполняется деструктор. Поэтому для вызова деструктора и удаления таких объектов применяется оператор delete:

1
2
Person *sam = new Person("Sam");
delete sam; // вызывается деструктор для объекта sam
Таким образом, у данной программы будет следующий консольный вывод:

Destructor called for Person Sam
End of Main
Destructor called for Person Tom
При этом выполнение самого деструктора еще не удаляет сам объект. Непосредственно удаление объекта производится в ходе явной фазы удаления, которая следует после выполнения деструктора.

Стоит также отметить, что для любого класса, который не определяет собственный деструктор, компилятор сам создает деструктор. Например, если бы класс Person не имел бы явно определенного деструктора, то для него автоматически создавался бы следующий деструктор:

1
~Person(){}