|
Программирование >> Операторы преобразования типа
Расп редел ител и памяти Распределители памяти были рассмотрены на с. 49. Они представляют собой специализированные абстракции, преобразующие потребности в памяти в непосредственные вызовы. Принципы работы распределителей памяти (далее - просто распределителей ) подробно рассматриваются в этой главе. 1спользование распределителей I прикладном программировании С точки зрения прикладного программиста, работать с разными распределителями памяти несаожно; достаточно передать нужный распределитель в аргументе шаблона. Например, следующий фрагмент создает разные контейнеры и строки с использованием специального распределителя МуАНосо: Вектор со специальным распределителем std::vector<int.KyAlloc<int> > v: Отображение int/float со специальным распределителем std;:niap<int. f 1 oat. 1 ess<1 nt>. MyAlloc<std::pa1r<const int,float> > > m; Строка со специальным распределителем std::bas1c string<char,std::char traits<char>.MyAlloc<char> > s; Если вы используете собственный распределитель памяти, вероятно, для пего стоит определить некоторые типы. Пример: Специальный строковый тип. использующий специальный распределитель typedef bas1c string<char,std::char traits<char>. MyAlloc<char> > xstring; Специальное отображение string/string со специальным распределителем typedef std: :niap<xstring.xstring.less<xstring>. MyAnoc<std: :pa1r<cDnst xstring.xstr1ng> xmap; Создание объекта типа xmap хшар щушар: Объекты с нестандартными распределителями памяти внешне ничем не отличаются от обычных объектов. Однако нельзя забывать, что элементы с разными распределителями не должны смешиваться; в противном случае возможны непредсказуемые последствия. Чтобы проверить, используют ли два распределителя одну модель памяти, воспользуйтесь оператором ==. Если оператор возвращает true, то память, выделенная одним распределителем, может быть освобождена через другой распределитель. Во всех типах, параметризованных по распределителю, определена функция get allocator(), предназначенная для получения объекта распределителя. Пример: if (rrymap.get al1ocatorO s.get allocator()) { ОК. mymap и s используют одинаковые или взаимозаменяемые распределители Использование распределителей при программировании библиотек Этот раздел посвящен использованию распределителей с точки зрения людей, занимающихся реализацией контейнеров и других компонентов, способных работать с разными распределителями. Материал этого раздела частично основан на разделе 19.4 книги Бьярна Страуструпа The С++ Programming Language*, 3rd Edition (с разрешения автора). Распределители предоставляют интерфейс для выделения и освобождения памяти, создания и уничтожения объектов (табл. 15.1). Распределители делают возможной параметризацию контейнеров и алгоритмов по способу хранения элементов. Например, они могут работать с общей памятью или отображать элементы на записи базы данных. Таблица 15.1. Основные операции распределителей Выражение Описание a.allocate(num) Выделение памяти для num элементов a.construct(p) Инициализация элемента, на который ссылается указатель р a.destroy(p) Уничтожение элемента, на который ссылается указатель р a.deallocate(p, num) Освобождение памяти для num элементов, на которую ссылается указатель р В качестве примера рассмотрим упрощенную реализацию вектора. Вектор получает распределитель памяти в виде аргумента шаблона или конструктора и сохраняет ее в своем внутреннем представлении: namespace std { template <class Т, class Allocator = allocator<T> > Использование распределителей при программировании библиотек /U3 class vector { private: Allocator alloc; Распределитель Т* elems: Массив элементов size type nuniElems; Количество элементов s1ze type sizeElems; Объем памяти для хранения элементов public: Конструкторы explicit vector(const Allocator&-Allocator()): explicit vector(size type num. const T& val=T(), const Allocators - AllocatorO): template <class InputIterator> vector(Inputlterator beg. Inputlterator end. const Allocators = AllocatorO): vectorCconst vector<T.Allocator>& v); Возможная реализация второго конструктора, инициализирующего вектор num элементами со значением val, может выглядеть так: namespace std { template <class Т. class Allocator> vector<T.Allocator>:;vector(size type num, const T& val. const Allocators a) : alloc(a) Инициализация распределителя Выделение памяти SizeElems = numElems = num: elems = alloc.allocate(num); Инициализация элементов for (size type 1=0: i<num; ++1) { Инициализация i-ro элемента all ос.construct(&elems[1].val); В стандартную библиотеку С++ включены также вспомогательные функции для инициализации неинициализированной памяти (табл. 15.2). При использовании этих функций реализацтщ конструктора выглядит еще проще: namespace std { template <c1ass Т. class Allocatoo vector<T.Allocator>::vector(s1ze type num. const T& val. const Allocator& a) : alloc(a) Инициализация распределителя
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |