Бьерн Страуструп.
Язык программирования С++
367
static Pool my_pool;
//
...
public:
//
...
void* operator new(size_t) { return my_pool.alloc(); }
void operator delete(void* p) { my_pool.free(p); }
};
Pool X::my_pool(sizeof(X));
С
помощью класса Pool память распределяется блоками одного размера. В приведенном примере
объект my_pool отводит память блоками размером sizeof(X).
Составляется описание класса X и используется Pool с учетом оптимизации скорости программы и
компактности представления. Обратите внимание, что размер выделяемых блоков памяти является для
класса "встроенным", поэтому задающий размер параметр функции X::operator new() не используется.
Используется вариант функции X::operator delete() без параметра. Если класс Y является производным
класса X, и sizeof(Y)>sizeof(X), то для класса Y должны быть свои
функции размещения и
освобождения. Наследование функций класса X приведет к катастрофе. К счастью, задать такие
функции для Y очень просто.
Класс Pool предоставляет связанный список элементов требуемого размера. Элементы выделяются из
блока памяти фиксированного размера и по мере надобности запрашиваются новые блоки памяти.
Элементы группируются большими блоками, чтобы минимизировать число обращений за памятью к
функции размещения общего назначения. До тех пор пока не будет уничтожен сам объект PooL, память
никогда не возвращается функции размещения общего назначения.
Приведем описание класса Pool:
class Pool {
struct Link { Link* next; }
const unsigned esize;
Link*
head;
Pool(Pool&); // защита от копирования
void operator= (Pool&); // защита от копирования
void
grow();
public:
Pool(unsigned
n);
~Pool();
void*
alloc();
void
free(void*
b);
};
inline void* Pool::alloc()
{
if (head==0) grow();
Link* p = head;
head = p->next;
return
p;
}
inline void Pool::free(void* b)
{
Link* p = (Link*) b;
p->next = head;
head = p;
}
Приведенные описания логично поместить в заголовочный файл Pool.h. Следующие определения могут
находиться в любом месте программе и завершают наш пример. Объект Pool должен
инициализироваться конструктором:
Бьерн Страуструп.
Язык программирования С++
368
Pool::Pool(unsigned sz) : esize(sz)
{
head = 0;
}
Функция Pool::grow() будет связывать все элементы в список квантов свободной памяти head, образуя
из них новый блок. Определения остальных
функций-членов оставлены в качестве упражнений 5 и 6 в
$$13.11.
void Pool::grow()
{
const int overhead = 12;
const int chunk_size = 8*1024-overhead;
const int nelem = (chunk_size-esize)/esize;
char* start = new char[chunk_size];
char* last = &start[(nelem-1)*esize];
for (char* p = start; p
((Link*)p)->next
=
((Link*)p)+1;
((Link*)last)->next = 0;
head = (Link*)start;
}
Достарыңызбен бөлісу: