Главная arrow С++ (часть 3) arrow Эффект выхода объекта GCPtr за пределы области видимости до ее завершения

Эффект выхода объекта GCPtr за пределы области видимости до ее завершения

В листинге 2.3 приводится пример программы, демонстрирующий эффект выхода объекта GCPtr за пределы области видимости до ее завершения.
ГП^5------------------------------------------------------------------------------------------------------------------------------------J
Листинг 2.3. Более интересный пример
// Показывает выход объекта GCPtr за пределы области видимости 11 До завершения программы, ¦include <iostream> ¦include <new> ¦include "gc.h"
Using namespace std;
int main()  ( GCPtr<int> p; GCPtr<int> q;
try {
p = new int(10); q = new int(11);
cout « "Value at p is: " « *p « endl; cout « "Value at q is: " « *q « endl;
cout « "Before entering block.\n";
// Теперь создадим локальный объект. {   // Начало блока.
GCPtr<int> г = new int(12);
cout « "Value at r is: " « *r « endl; }    // Конец блока, вызывающий выход г за пределы области видимости.
cout « "After exiting block.\n";
} catch(bad_alloc exc) {
cout « "Allocation failure!\n"; return 1;
}
cout « "Done\n"; return 0;
}
Если включен режим отображения, приведенная программа выводит на экран следующую информацию. Constructing GCPtr. Constructing GCPtr. Value at p is: 10 Value at q is: 11 Before entering block.
Constructing GCPtr.
Value at r is: 12
GCPtr going out of scope.
Before garbage collection for gclist<inc, 0>:
memPtr       refcount       value
[002F31D8] 0 12
[002F12FO] 1 11
[002F12CO] 1 10
[00000000] 0
Deleting: 12
After garbage collection for gclist<int, 0>: memPtr        refcount    value
[002F12FO] 1 11
[002F12CO] 1 10
After exiting block. Done
GCPtr going out of scope.
Before garbage collection for gclist<int, 0>: memPtr       refcount    value [002F12FO] 0 11
[002F12C0] 1 10
Deleting: 11
After garbage collection for gclist<int, 0>: roemPtr       refcount    value [002F12C0] 1 10
GCPtr going out of scope.
Before garbage collection for gclist<int, 0>: ""emPtr       refcount    value 1002F12CO] 0 10
dieting:  10
After garbage collection for gclist<int, 0>: ""^tr        refcount     value — Empty —
Обсудим подробно приведенные код программы и результаты ее выполнения. Прежде всего, отметим, что объекты р и q создаются при запуске main (), а объект г не создается до тех пор, пока не начнет выполняться его блок. Как вы знаете, в языке С++ локальные переменные не создаются до выполнения блока, в котором они объявлены. В момент создания объекта г памяти, на которую он указывает, присваивается начальное значение 12. Это значение выводится на экран, и блок заканчивается. Его завершение вызывает выход объекта г за пределы области видимости, что влечет за собой вызов его деструктора, который уменьшает до нуля счетчик ссылок, хранящийся в списке gclist и связанный с объектом г. Далее вызывается функция collect о для сбора мусора.
Поскольку включен режим отображения, после запуска функции collect о на экран выводится содержимое списка gclist. В нем четыре элемента. Первый из них — тот, который прежде был связан с объектом г. Обратите внимание, что его счетчик ссылок (поле refcount) равен нулю, указывая на то, что фрагмент памяти, адрес которого хранится в поле memPtr, больше не используется ни одним программным элементом. Следующие 2 элемента еще активны и связаны с объектами q и р соответственно. Так как эти элементы — действующие, память, на которую они указывают, пока еще не освобождается. Последний элемент списка представляет неопределенный или пустой адрес (null pointer), на который ссылались объекты р и q в момент их создания. В данный момент он уже не используется и будет удален из списка функцией collect о (конечно, при этом никакая память не освобождается).
Память, ранее связанная с объектом г, очищается, так как нет других объектов типа GCPtr, указывающих на нее, что и подтверждается строкой на экране: "Deleting: 12 " (уничтожается 12). После того как это сделано, часть программы, расположенная после блока, продолжает выполняться. В конце, когда программа завершает работу, объекты р и q выходят за пределы области видимости, и память, на которую они указывают, освобождается. В данном случае деструктор объекта q вызывается первым, свидетельствуя о том, что сначала сборщик мусора обрабатывает этот объект. Затем уничтожается объект р и выводится на экран пустой список gclist.