обработку исключений, но целью этого примера является показать, как хранить один тип контейнеров в другом.

Для начала я создаю несколько typedef, облегчающих чтение кода.

typedef std::set<std::string> SetStr;

typedef std::map<std::string, SetStr*> MapStrSetStr;

При использовании шаблонов шаблонов (шаблонов… и т.д.) объявления становятся очень длинными, что затрудняет их чтение, так что облегчите себе жизнь, использовав typedef. Более того, использование typedef облегчает внесение изменений в объявление шаблонов, избавляя от необходимости выполнять поиск и замену во многих местах большого количества исходных файлов.

Класс DBConn — это фиктивный класс, который представляет подключение к реляционной базе данных. Интересно здесь то, как в SimpleTxnLog определяется метод addTxn. В начале этой функции я смотрю, существует ли уже объект набора для переданного id.

SetStr* pSet = log_[id];

log_ — это map (см. рецепт 6.6), так что operator[] выполняет поиск id и смотрит, связаны ли с ним какие-либо данные. Если да, то возвращается объект данных, и pSet не равен NULL. Если нет, он создается, и возвращается указатель, который будет равен NULL. Затем я проверяю, указывает ли на что-то pSet, и определяю, требуется ли создать еще один набор.

if (pSet == NULL) {

 pSet = new SetStr(); // SetStr = std::set<std::string>

 log_[id] = pSet;

}

Так как pSet — это копия объекта данных, хранящихся в map (указатель на набор), а не само значение, то после создания set я должен поместить его обратно в связанный с ним ключ в map. После этого все, что остается сделать, — это добавить элемент в набор и выйти.

pSet->insert(sql);

Выполнив указанные шаги, я в один контейнер (map) добавил указатель на адрес другого контейнера (set). Что я не делал — это добавление объекта set в map. Разница очень существенна. Так как контейнеры обладают семантикой копирования, следующий код приведет к копированию всего набора s в map.

set<string> s;

// Заполнить s данными...

log_[id] = s; // Скопировать s и добавить его копию в log_

Это приведет к огромному числу дополнительных нежелательных копирований. Следовательно, общее правило при использовании контейнеров из контейнеров — это использовать указатели на контейнеры.

Глава 7

Алгоритмы

7.0. Введение

Эта глава рассказывает, как работать со стандартными алгоритмами и как использовать их для стандартных контейнеров. Эти алгоритмы первоначально являлись частью того, что часто называется Standard Template Library (STL — стандартная библиотека шаблонов) и представляет собой набор алгоритмов, итераторов и контейнеров, которые теперь вошли в стандартную библиотеку (глава 6 содержит рецепты по работе со стандартными контейнерами). Я их буду называть просто стандартными алгоритмами, итераторами и контейнерами, но не забывайте, что это то же самое, что другие авторы называют частью STL. Одним из базовых элементов стандартной библиотеки являются итераторы, так что первый рецепт описывает, что они собой представляют и как их использовать. После этого идет несколько рецептов, которые объясняют, как использовать и расширять стандартные алгоритмы. Наконец, если вы не нашли ничего подходящего в стандартной библиотеке, то рецепт 7.10 расскажет, как написать собственный алгоритм.

Представленные здесь рецепты в основном предназначены для работы со стандартными контейнерами, и тому есть две причины. Во-первых, стандартные контейнеры очень распространены, и лучше изучить стандарт, чем изобретать колесо. Во-вторых, реализация алгоритмов из стандартной библиотеки предоставляет хороший пример для подражания в смысле взаимодействия и производительности. Если вы посмотрите, как профессионалы выполнили код стандартной библиотеки, вы, скорее всего, узнаете много нового и полезного для себя.

Все стандартные алгоритмы используют итераторы. Даже если вы знакомы с концепцией итераторов, которые рассматриваются в первом рецепте, посмотрите на табл. 7.1, которая содержит перечень соглашений, используемых в остальных рецептах главы при демонстрации объявлений функций стандартных алгоритмов.

Табл. 7.1. Сокращения категорий итераторов

Сокращение Значение
In Input iterator (Итератор ввода)
Out Output iterator (Итератор вывода)
Fwd Forward iterator (Однонаправленный итератор)
Bid Bidirectional iterator (Двунаправленный итератор)
Rand Random-access iterator (Итератор произвольного доступа)
Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату