Книги
чёрным по белому
Главное меню
Главная О нас Добавить материал Поиск по сайту Карта книг Карта сайта
Книги
Археология Архитектура Бизнес Биология Ветеринария Военная промышленность География Геология Гороскоп Дизайн Журналы Инженерия Информационные ресурсы Искусство История Компьютерная литература Криптология Кулинария Культура Лингвистика Математика Медицина Менеджмент Металлургия Минералогия Музыка Научная литература Нумизматика Образование Охота Педагогика Политика Промышленные производства Психология Путеводители Религия Рыбалка Садоводство Саморазвитие Семиотика Социология Спорт Столярное дело Строительство Техника Туризм Фантастика Физика Футурология Химия Художественная литература Экология Экономика Электроника Энергетика Этика Юриспруденция
Новые книги
Цуканов Б.И. "Время в психике человека" (Медицина)

Суворов С. "Танк Т-64. Первенец танков 2-го поколения " (Военная промышленность)

Нестеров В.А. "Основы проэктирования ракет класса воздух- воздух и авиационных катапульных установок для них" (Военная промышленность)

Фогль Б. "101 вопрос, который задала бы ваша кошка своему ветеринару если бы умела говорить" (Ветеринария)

Яблоков Н.П. "Криминалистика" (Юриспруденция)
Реклама

Эффективное использование STL. Библиотека программиста - Мейерс С.

Мейерс С. Эффективное использование STL. Библиотека программиста — Спб.: Питер , 2002. — 224 c.
ISBN 5-94723-382-7
Скачать (прямая ссылка): effektivnoeispolzovaniestlbibliote2002.djvu
Предыдущая << 1 .. 24 25 26 27 28 29 < 30 > 31 32 33 34 35 36 .. 114 >> Следующая

указателя (на следующий и предыдущий узлы списка).
tempiate<typename Т. // Возможная реализация
typename Allocator=allocator<T" // списка
class list{ private:
Allocator alloc: // Распределитель памяти для объектов типа Т
struct ListNode{ // Узлы связанного списка
Т data;
ListNode *prev;
ListNode *next;
}:
}:
При включении в список нового узла необходимо получить для него память от
распределителя, однако нам нужна память не для Т, а для структуры
ListNode, содержащей Т. Таким образом, объект Allocator становится
практически бесполезным, потому что он выделяет память не для ListNode, а
для Т. Теперь становится понятно, почему 1 i st никогда не обращается к
А11 ocator за памятью - последний просто не способен предоставить то, что
требуется 1 i st.
Следовательно, 1 i st нужны средства для перехода от имеющегося типа
распределителя к соответствующему распределителю Li stNode. Задача была
бы весьма непростой, но по правилам распределитель памяти должен
предоставить определение типа для решения этой задачи. Определение
называется other, но не все так просто - это определение вложено в
структуру с именем rebind, которая сама по себе является шаблоном,
вложенным в распределитель, - причем последний тоже является шаблоном!
Пожалуйста, не пытайтесь вникать в смысл последней фразы. Вместо этого
просто рассмотрите следующий фрагмент и переходите к дальнейшему
объяснению:
tempiate<typename Т> class allocator} public:
tempiate<typename U> struct rebind{
typedef allocator<U> other:
}:
Совет 10 59
В программе, реализующей list<T>, возникает необходимость определить тип
распределителя ListNode, соответствующего распределителю, существующему
для Т. Тип распределителя для Т задается параметром А11 ocator. Учитывая
сказанное, тип распределителя для Li stNode должен выглядеть так:
Allocator::rebind<ListNode>::other
А теперь будьте внимательны. Каждый шаблон распределителя А (например,
std: :allocator, SpecialAllocator и т. д.) должен содержать вложенный
шаблон структуры с именем rebind. Предполагается, что rebind получает
параметр U и не определяет ничего, кроме определения типа other, где
other - просто имя для A<U>. В результате 1 i st<T> может перейти от
своего распределителя объектов Т (А! 1 ocator) к распределителю объектов
Li stNode по ссылке А11 ocator:: rebi nd<Li stNode>:: other.
Может, вы разобрались во всем сказанном, а может, и нет (если думать
достаточно долго, вы непременно разберетесь, но подумать придется - знаю
по своему опыту). Но вам как пользователю STL, желающему написать
собственный распределитель памяти, в действительности не нужно точно
понимать суть происходящего. Достаточно знать простой факт: если вы
собираетесь создать распределитель памяти и использовать его со
стандартными контейнерами, ваш распределитель должен предоставлять шаблон
rebi nd, поскольку стандартные шаблоны будут на это рассчитывать (для
целей отладки также желательно понимать, почему узловые контейнеры Т
никогда не запрашивают память у распределителей объектов Т).
Ура! Наше знакомство со странностями распределителей памяти закончено.
Позвольте подвести краткий итог того, о чем необходимо помнить при
программировании собственных распределителей памяти:
• распределитель памяти оформляется в виде шаблона с параметром Т,
представляющим тип объектов, для которых выделяется память;
• предоставьте определения типов pointer и reference, но следите за
тем, чтобы pointer всегда был эквивалентен Т*, a reference - Т&;
• никогда не включайте в распределители данные состояния"уровня
объекта. В общем случае распределитель не может содержать нестатических
переменных;
• помните, что функциям al 1 ocate передается количество объектов,
для которых необходимо выделить память, а не объем памяти в байтах. Также
помните, что эти функции возвращают указатели Т* (через определение типа
poi nter) несмотря на то, что ни один объект Т еще не сконструирован;
• обязательно предоставьте вложенный шаблон rebind, от наличия
которого зависит работа стандартных контейнеров.
Написание собственного распределителя памяти обычно сводится к
копированию приличного объема стандартного кода и последующей модификации
нескольких функций (в первую очередь al 1 ocate и deal 1 ocate). Вместо
того чтобы писать базовый код с самого начала, я рекомендую
воспользоваться кодом с web-страницы Джосаттиса [23] или из статьи
Остерна "What Are Allocators Good For?" [24].
Материал, изложенный в этом совете, дает представление о том, чего не
могут сделать распределители памяти, но вас, вероятно, больше интересует
другой вопрос - что они могут? Это весьма обширная тема, которую я
выделил в совет 11.
60 Глава 1 • Контейнеры
Совет 11. Учитывайте область применения пользовательских распределителей
памяти
Итак, в результате хронометража, профилирования и всевозможных
экспериментов вы пришли к выводу, что стандартный распределитель памяти
STL (то есть allocator<T>) работает слишком медленно, напрасно расходует
Предыдущая << 1 .. 24 25 26 27 28 29 < 30 > 31 32 33 34 35 36 .. 114 >> Следующая