struct name (* char* string; name* next; double value;
name(char*, double, name*); ~name(); *);
Программист может воспользоваться тем, что размещение и освобождение объектов заранее известного размера можно обрбатывать гораздо эффективнее (и по памяти, и по времени), чем с помощью общей реализации new и delete. Общая идея состоит в том, чтобы предварительно разместить «куски» из объектов name, а затем сцеплять их, чтобы свести выделение и освободение к простым операциям над связанным списком. Переменная nfree является вершиной списка неиспользованных name:
const NALL = 128; name* nfree;
Распределитель, используемый операцией new, хранит рамер объекта вместе с объектом, чтобы обеспечить правильную работу операции delete. С помощью распределителя, специализрованного для типа, можно избежать этих накладных расходов. Например, на моей машине следующий распределитель использует для хранения name 16 байт, тогда как для стандартного распрделителя свободной памяти нужно 20 байт. Вот как это можно сделать:
name::name(char* s, double v, name* n) (* register name* p = nfree; // сначала выделить
if (p) nfree = p-»next; else (* // выделить и сцепить name* q = (name*)new char[ NALL*sizeof(name) ]; for (p=nfree= amp;q[NALL-1]; q«p; p–) p-»next = p-1; (p+1)-»next = 0; *)
this = p; // затем инициализировать string = s; value = v; next = n; *)
Присвоение указателю this информирует компилятор о том, что программист взял себе управление, и что не надо использвать стандартный механизм распределения памяти. Конструктор name::name() обрабатывает только тот случай, когда name рамещается посредством new, но для большей части типов это всегда так. В #5.5.8 объясняется, как написать конструктор для обработки как размещения в свободной памяти, так и других видов размещения.
Заметьте, что просто как
name* q = new name[NALL];
память выделять нельзя, поскольку это приведет к бескнечной рекурсии, когда new вызовет name::name().
Освобождение памяти обычно тривиально:
name::~name() (* next = nfree; nfree = this; this = 0; *)
Присваивание указателю this 0 в деструкторе обеспечивет, что стандартный распределитель памяти не используется.
Когда в конструкторе производится указателю this, значние this до этого присваивания неопределено. Таким образом, ссылка на член до этого присваивания неопределена и скорее всего приведет к катастрофе. Имеющийся компилятор не пытается убедиться в том, что присваивание указателю this происходит на всех траекториях выполнения:
mytype::mytype(int i) (* if (i) this = mytype_alloc(); // присваивание членам *);