Программирование >>  Формирование пользовательского контейнера 

1 ... 12 13 14 [ 15 ] 16 17 18 ... 156


return rv;

p->refcount-;

Далее, если новый адрес уже

существует в системе, увеличивает на единицу

его счетчик ссылок. В противном случае создает новый

элемент в списке gclist.

р = findPtrlnfo(t);

if(p != gclist.endO)

p->refcount++; else {

Создает и запоминает новый элемент. GCInfo<T> gcCbj(t, size); gclist.push front(gcCbj);

addr = t; запоминает адрес, return t;

Перегружает присваивание одного GCPtr другому GCPtr. tenplate <class T, int size>

GCPtr<T, size> & GCPtr<T, size>::operator=(GCPtr &rv) { list<GCInfo<T> >::iterator p;

Сначала уменьшает на единицу счетчик ссылок для памяти, указываемой в данный момент, р = findPtrlnfo(addr); p->refcount-;

Далее увеличивает счетчик ссылок для

нового адреса.

р = findPtrlnfo(rv.addr);

p->refcount++; увеличивает счетчик ссылок addr = rv.addr; запоминает адрес.



Первый вариант перегрузки, operator=(), поддерживает присваивания, в которых указатель класса GCPtr стоит слева, а адрес - справа. Далее приведены примеры такой перегрузки операции.

GCPtr<int> р; ...

р = new int(18);

В приведенном примере адрес, полученный операцией new, присваивается о&ьекту р. В этот момент вызывается операция operator=(T *t) с новым адресом, передаваемым в t. Сначала в списке gclist ищется элемент с текущим значением адреса, и его счетчик ссылок уменьшается на единицу. Далее в списке gclist выполняется поиск элемента с новым значением адреса. Если такой элемент в списке есть, его счетчик ссылок увеличивается на единицу. В противном случае создается объект типа ocinfo для нового значения адреса, и этот элемент добавляется в список gclist. В завершение, новый адрес сохраняется в поле addr инициированного объекта, и этот адрес возвращается.

Второй вариант перегрузки, operator= (ocptr erv), поддерживает следующий тип присваивания:

GCPtr<int> р; GCPtr<int> q; ...

р = new(88); q = р;

В приведенном фрагменте кода р и q - указатели класса ocptr, и значение р присваивается q. Этот вариант присваивания действует почти так же, как предыдущий. Сначала в списке gclist ищется элемент с текущим значением адреса и его счетчик ссылок уменьшается на единицу. Далее просматривается список gclist для поиска элемента с новым значением адреса, который содержится в переменной rv.addr, и счетчик ссылок такого элемента увеличивается. Затем в поле addr найденного объекта помещается значение, хранящееся в переменной rv.addr. В завершение, возвращается объект из правой части операции присваивания. Подобный механизм позволяет выполнять цепочку присваиваний, такую как:

Р = q = W = z;

Есть еще одна особенность выполнения описанных операций присваивания, на которую следует обратить внимание. Как упоминалось ранее в этой главе, технически можно очищать память, как только связанный с ней счетчик ссылок станет равным нулю, но такой подход вносит дополнительные расходы При выполнении любой операции с указателями. Именно поэтому в перегруженных операциях присваивания счетчик ссылок, связанный с памятью.



адрес которой указан в левой части выражения присваивания, просто уменьшается на единицу без каких-либо дополнительных действий. Таким образом, удается избежать расходов управления, связанных с реальной очисткой динамической памяти и сопровождением списка gclist. Все необходимые для этого действия откладываются до реального запуска процесса сбора мусора. Подобный подход выбран для повышения производительности кода, используюшего класс GCPtr. Он также позволяет выполнять сбор мусора в более удобное (потенциально) время с точки зрения производительности выполнения программы.

Копирующий конструктор класса GCPtr

Из-за необходимости отслеживать связь указателя с выделенной памятью нельзя применять стандартный копирующий конструктор (создающий поразрядную идентичную копию). Вместо этого класс ocptr должен определить собственный конструктор копирования, приведенный далее.

Копирующий конструктор. GCPtr(const GCPtr &ob) {

list<GCInfo<T> >::iterator p;

p = findPtrlnfo(ob.addr);

p->refcount++; увеличивает счетчик ссылок

addr = Ob.addr;

arraySize = ob.arraySize;

if (arraySize > 0) isfArray = true;

else isArray = false;

#ifdef DISPLAY

cout Constructing copy. ;

if(isArray) cout Size is arraySize endl;

else cout endl; ttendif

Напоминаю, что копирующий конструктор класса вызывается, если требуется копия объекта в тех случаях, когда объект передается как параметр функции и возвращается функцией, или когда один объект используется для инициализации другого объекта. Копирующий конструктор класса GCPtr дублирует информацию, содержащуюся в объекте-оригинале. Он также увеличивает на единицу счетчик ссылок, связанный с фрагментом памяти.



1 ... 12 13 14 [ 15 ] 16 17 18 ... 156

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика