Деструктор - это специальная функция-член класса, выполняемая всякий раз, когда объект его класса выходит из области видимости или всякий раз, когда выражение удаления применяется к указателю на объект этого класса.
Деструктор будет иметь то же имя, что и класс с префиксом тильды ~
, и он не может ни возвращать значение, ни принимать какие-либо параметры. Деструктор может быть очень полезен для освобождения ресурсов перед выходом из программы, как закрытие файлов, освобождая память и т.д.
Деструктор вызывается, когда объект прижизненной заканчивается, который включает в себя
- завершение программы, для объектов с продолжительность хранения статической
- нить выход, для объектов с продолжительностью хранения локального потока (так как C++ 11)
- конец рамки, для объектов с автоматической продолжительности хранения и временных чья жизнь была расширена за счет связывания с a reference,
- delete-expression, для объектов с динамической продолжительностью хранения, конец полное выражение для безымянных времен;
- стека разматывается, для объектов с автоматическим временем хранения, когда исключение исключает их блок, неотображается.
Деструктор также может быть вызван непосредственно, например. для уничтожения объекта, который был создан с использованием функции размещения-new или через функцию-член распределителя, например std::allocator::destroy()
, для уничтожения объекта, который был сконструирован через распределитель. Обратите внимание, что вызов деструктора непосредственно для обычного объекта, такого как локальная переменная, вызывает неопределенное поведение, когда деструктор вызывается снова, в конце области.
В общих контекста синтаксис вызова деструктора может использоваться с объектом типа неклассов; это называется вызовом псевдо-деструктора: см. оператор доступа к члену.
Косвенно объявленная деструктор:
Если ни один определенный пользователем деструктор не предусмотрен для типа класса (struct
, class
или union
), компилятор всегда будет объявить деструктор как inline
public
членом его класс.
Исключены неявно объявлено деструктор:
неявно объявленный или просроченный деструктор class T
не определено (до C++ 11) определяется как удаленный (так как C++, 11), если любой из следующих условий верно:
- Т имеет нестатический элемент данных, который не может быть (разрушенный производственным было удален или недоступен деструктор)
- Т имеет прямой или виртуальный базовый класс, который не может быть разрушенным производственным (имеет удаленных или недоступных деструкторов)
- T является объединением и имеет вариантный элемент с нетривиальным деструктором. (так как C++ 11)
неявно объявленная деструктор virtual
(так как базовый класс имеет виртуальный деструктор) и поиск для функции Deallocation (оператор Delete() приводит к вызову к неоднозначным, удалены или недоступны функции Trivial деструктор
деструктор для class T
тривиальна, если все верно следующее:..
- деструктор не предоставленные пользователем (значение, это неявно определяются или просроченный)
- деструктора не является виртуальным (то есть базовым класс деструктор не виртуальный)
- Всех классов прямых оснований имеют тривиальные деструкторы
- Все не статические данные типа класса (или массив типа класса) имеют тривиальные деструкторы
тривиальный деструктор деструктор, который не выполняет никаких действий. Объекты с тривиальными деструкторами не требуют удаления-выражения и могут быть удалены путем простого освобождения их хранения. Все типы данных, совместимые с языком C (типы POD), тривиально разрушаются.
Косвенно определенный деструктор:
Если неявно объявленный деструктор не удаляется или тривиальными, оно определено (то есть тело функции генерируется и компилируется) компилятором. Этот неявно определенный деструктор имеет пустое тело.
Как и любая неявно определенная специальная функция-член, спецификация исключения неявно определяемого деструктора является не-бросанием, если она непосредственно вызывает функцию с другой спецификацией исключения (например, когда она должна вызывать определяемый пользователем деструктор для член или базовый подобъект с другой спецификацией исключения).
Destruction последовательность:
Для оба определяемого пользователя или неявно определенные деструкторов, после того, как тело деструктора выполняется, компилятор вызывает деструкторы для всех нестатических нечленов вариантного класса , в обратном порядке объявления, то он вызывает деструкторы всех прямых базовых классов в обратном порядке построения (которые, в свою очередь, называют деструкторы их членов и их базовых классов и т. д.), а затем, если этот объект имеет наибольшее значение, производный класс, он называет деструкторы всех виртуальных баз.
Даже когда деструктор вызывается непосредственно (например, obj.~Foo();
), оператор возврата в ~Foo()
не возвращает управление вызывающему абоненту сразу: он вызывает все эти элементы и базовые деструкторы.
Виртуальные деструкторы:
Удаление объекта через указатель на базу вызывает неопределенное поведение, если деструктор в базовом классе не является виртуальным:
class Base {
public:
virtual ~Base() {}
};
class Derived : public Base {};
Base* b = new Derived;
delete b; // safe
Общий принцип таков, что деструктор для базы класс должен быть открытым или виртуальным или защищенным и не виртуальным Чистые виртуальные деструкторы Деструктор может быть объявлен чистым виртуальным, например, в базовом классе, который необходимо сделать абстрактным, но не имеет другого подходящего f которые могут быть объявлены чистыми виртуальными. Такой деструктор должен иметь определение, так как все деструкторы базового класса всегда вызывается, когда производный класс будет уничтожен:
class AbstractBase {
public:
virtual ~AbstractBase() = 0;
};
AbstractBase::~AbstractBase() {}
class Derived : public AbstractBase {};
// AbstractBase obj; // compiler error
Derived obj; // OK
Исключения:
Как и любой другой функции, деструктор может прекратить путем бросать исключение (обычно это требует, чтобы он явно объявлялся noexcept (false)) (начиная с C++ 11), однако, если этот деструктор вызван во время разматывания стека, вместо него вызывается std :: terminate. Хотя std :: uncaught_exception иногда может использоваться для обнаружения процесса разворачивания стека, обычно считается неправильной практикой, чтобы любой деструктор мог завершиться путем выброса исключения. Одним из примеров использования этой функциональности является библиотека SOCI, которая опирается на способность деструкторов определенных безымянных временных файлов генерировать исключения.
Пример: Запустить данный код.
#include <iostream>
struct A
{
int i;
A (int i) : i (i) {}
~A()
{
std::cout << "~a" << i << std::endl;
}
};
int main()
{
A a1(1);
A* p;
{ // nested scope
A a2(2);
p = new A(3);
} // a2 out of scope
delete p; // calls the destructor of a3
}
Выход:
~a2
~a3
~a1
содержание взяты из http://en.cppreference.com/w/cpp/language/destructor
Я думаю, что это может помочь http://en.cppreference.com/w/cpp/language/destructor, а также многие другие статьи о деструкторах. – vahancho
Да, это деструктор, и это уже было описано здесь: [деструктор] [1] [1]: http://stackoverflow.com/questions/1395506/in-c-what-does -a-тильда перед тем-а-имя-функции-обозначения – Lui