|
Программирование >> Операторы преобразования типа
Распределитель по умолчанию 707 Удаление элементов инициализированного блока р void destroy(pointer р): Освобождение блока р с удаленными элементами void deal!ocate(pointer p, size type num); Распределитель no умолчанию выделяет и освобождает память глобальными операторами new и delete. Это означает, что вызов allocate() может сгенерировать исключение bad alloc. Однако распределтттель по умолчанию можно оптимизировать за счет повторного использования освобожденной памяти или выделения линптей памяти для экономии времени на дополнительных перераспределениях. Следовательно, моменты вызова операторов new и delete точно не известны. Возможная реализация пользовательского распределителя приведена на с. 708. Внутри шаблона распределителя имеется несколько необычпое определение шаблонной структуры rebind. Эта шаблонная структура дает возможность косвенного выделения памяти другого типа. Например, если распределитель относится к типу Allocator, то следующая конструкция определяет тип того же распределителя, специализированного для элементов тина Т2: Allocator::rebind<T2>:;other Представьте, что при реализации контейнера вам потребовалось выделить память для типа, отличного от типа элементов. Например, при реализации дека обычно приходится выделять память для массивов, управляющих блоками элементов (типичная реализация дека представлена на с. 169). Следовательно, вам понадобится распределитель для выделения массивов указателей на элементы: namespace std { template <class Т. class Allocator = allocator<T> > class deque { private; Привязка распределителя к типу Т* typedef typename Allocator::reb1nd<T*>;:other PtrAllocator; Allocator alloc: Распределитель для значений типа Т PtrAllocator block alloc; Распределитель для значений типа Т* Т** elems; Массив блоков элементов При управлении элементами дека один распределитель должен работать с блоками элементов, а другой - с массивом блоков элементов. Последний относится к типу PtrAllocator. При помощи структуры rebindo распределитель элементов (Allocator) привязывается к типу массива элементов (Т*). Распределитель по умолчанию имеет следующую специализацию для тина void: namespace std { template <> class allocator<void> { public: typedef void* pointer; typedef const void* const po1nter; typedef void value type; template <class U> struct rebind { typedef anocator<U> other; Пользовательский распределитель Написать собственный распределитель не так уж сложно. Самый важный вопрос - как будет организовано вьщеление или освобождение памяти? Все остальное более или менее очевидно. Для примера рассмотрим упрощенную реализацию распределителя по умолчанию: util/defallochpp namespace std { template <class T> class allocator { public: Определения типов typedef s1ze t s1ze type; typedef ptrdiff t d1fference type; typedef T* pointer; typedef const T* const po1nter: typedef TS reference; typedef const TS const reference: typedef T value type: Привязка распределителя к типу U template <class U> struct rebind { typedef allocator<U> other; Функции возвращают адреса значений pointer address (reference value) const ( return Svalue; const pointer address (const reference value) const { return Svalue; /* Конструкторы и деструктор * - ничего не делаем, поскольку распределитель не имеет состояния */ allocatorO throwO { } allocator(const allocators) throwO { } template <class U> allocator {const allocator<U>&) throwO { -allocatorO throwO { } Функция возвращает максимальное количество элементов. для которых может быть выделена память sl2e type rrax s1ze {) const throwO { return numericjlmits<size t>; :max{) / sizeof(T); Выделение памяти для num элементов типа Т без инициализации pointer allocate (size type num. allocator<void>;:const pointer hint = 0) { allocate memory with global new return (pointer)(::operator new(num*sizeof(T))); Инициализация элементов выделенного блока р значением value void construct (pointer p. const T& value) { Инициализация памяти оператором new new((void*)p)T(value): Удаление элементов инициализированного блока р void destroy (pointer р) { Уничтожение обьектов вызовом деструктора р->-Т(): Освобождение блока р. содержащего удаленные эпементы void deallocate (pointer p. size type num) { Освобождение памяти глобальным оператором delete -operator delete((vo1d*)p);
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |