Управление сборкой мусора
В документации по языкам .NET вы могли встречать описание метода Finalize (Завершить), используемого для освобождения ресурсов, не находящихся в управляемой динамически распределяемой области памяти, но созданных управляемыми объектами. Однако в C++ реализовывать данный метод не надо. Если же все-таки сделать это, компилятор выдаст сообщение об ошибке, указав, что вместо метода Finalize (Завершить) для управляемого класса требуется определить деструктор. Сборщик мусора автоматически вызовет деструктор (в отдельном потоке) при освобождении памяти, занятой объектом; но момент вызова деструктора не определен. А это значит: не следует рассчитывать на то, что деструктор будет вызван при удалении ссылки на объект.
Если вы реализовали деструктор и удаляете управляемый объект явно, деструктор будет вызван сразу, и сборщик мусора уже не будет его вызывать. Можно также, вызвав статический метод GC::Collect () (Сборщик мусора::Собрать()), вынудить сборщик мусора попытаться освободить память из-под объекта, а вызов деструктора синхронизировать с завершением работы сборщика мусора при помощи статического метода GC::WaitForPending-Finalizers. Впрочем, обычно неудобно и неэффективно вызывать сборку мусора принудительно или синхронизовать ее с вызовом деструктора, поэтому, если необходимо выполнять очистку в определенный момент, рекомендуется реализовать это независимо в отдельном методе, а затем вызывать его явным образом. Этот метод рекомендуется называть Dispose (Ликвидировать).
Рассмотрим следующую программу.
//ManagingGC.срр fusing <mscorlib.dll> using namespace System; // использовать пространство имен Система; _gc class ManagedClass // класс сборщика мусора ManagedClass { public: ManagedClass () { Console::WriteLine("c'tor"); } ~ManagedClass () { Console::WriteLine("d'tor"); } }; void main(void) { Console::WriteLine("start"); // начало ManagedClass *pmc = new ManagedClass; // Раскомментируйте следующую строку // для предотвращения вызова деструктора //GC::SuppressFinalize(pmc); // СБОРЩИК МУСОРА Console::WriteLine("middle"); // середина // Раскомментируйте следующую строку // чтобы вызвать деструктор пораньше //delete pmc; // удалить pmc = 0; //… или две следующие строки для того, // чтобы вызвать деструктор пораньше //GC::Collect(); // СБОРЩИК МУСОРА:: Собрать //GC:-.WaitForPendingFinalizers (); // СБОРЩИК МУСОРА Console::WriteLine("end"); // конец }
Приведем результат работы программы. Обратите внимание, что деструктор вызывается после того, как программа напечатает end (конец).
start // начало c'tor middle // середина end // конец d'tor
Однако, если раскомментировать строку, содержащую вызов метода SuppressFinalize, деструктор не будет вызван вообще, что доказывается следующей выдачей.
start // начало с' tor middle // середина end // конец
Кроме того, если раскомментировать оператор, в котором используется delete (удалить), деструктор будет вызван до того, как программа напечатает end (конец).
start // начало c'tor middle // середина d'tor end // конец
Наконец, если раскомментировать только два оператора, содержащих вызовы методов Collect (Собрать) и WaitForPendingFinalizers, деструктор опять будет вызван до того, как программа напечатает end (конец) В этом случае вызов метода Collect (Собрать) приводит к вы зову деструктора, а метод WaitForPendingFinalizers приостанавливает выполнение текущего потока до завершения работы деструктора.
start // начало c'tor middle // середина d'tor end // конец