Материалы книги получены с http://www.itlibitum.ru/
Аргументы оператора new
Оператор new можно перегрузить так, чтобы помимо размера он вызывался и с другими
дополнительными аргументами. Перегрузка лишает вас стандартной сигнатуры void* operator
new(size_t), и, если вам этого не хочется, ее придется включить в программу вручную.
#define kPoolSize 4096
struct Pool {
unsigned char* next; // Следующий свободный байт
unsigned char space[kPoolSize];
Pool() : next(&space[0]) {}
};
class Foo {
public:
void* operator new(size_t bytes)
{ return ::operator new(bytes); }
void* operator new(size_t bytes, Pool* pool)
{
void* space = pool->next;
pool->next += bytes;
return space;
}
};
void f()
{
Pool localPool;
Foo* foo1 = new Foo; // Использует оператор new по умолчанию
Foo* foo2 = new(&localPool) Foo; // Использует перегрузку
}
Здесь клиент, а не класс указывает, где следует разместить объект. Показан лишь фрагмент полной стратегии. Например, как оператор delete узнает, откуда была взята память - из глобального пула, используемого оператором new по умолчанию, или настандартного пула, который используется перегруженным оператором new? Впрочем, основная идея проста: предоставить клиенту класса некоторую степень контроля над размещением экземпляров в памяти. Это означает, что способ выделения памяти может выбираться для конкретных объектов и не обязан совпадать для всех экземпляров класса.
Оператор new можно перегружать с любыми новыми сигнатурами при условии, что все они
различаются, а первым аргументом каждой перегруженной версии является size_t - количество нужных байт. Перегрузки могут быть как глобальными, так и принадлежать конкретным классам. Когда компилятор встречает аргументы между new и именем класса, он подставляет размер в начало списка аргументов и ищет подходящую сигнатуру.
Назад Содержание Далее
|