Пример 6.12 предлагает ситуацию, где может потребоваться хранение одного контейнера в другом. Представьте, что требуется сохранить набор выражений SQL в виде пакета, выполнить их в будущем все сразу для реляционной базы данных. Именно это делает SimpleTxnLog
Для начала я создаю несколько typedef
typedef std::set
typedef std::map
При использовании шаблонов шаблонов (шаблонов… и т.д.) объявления становятся очень длинными, что затрудняет их чтение, так что облегчите себе жизнь, использовав 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
log_[id] = pSet;
}
Так как pSet
set
я должен поместить его обратно в связанный с ним ключ в map
. После этого все, что остается сделать, — это добавить элемент в набор и выйти.pSet->insert(sql);
Выполнив указанные шаги, я в один контейнер (map
set
). Что я не делал — это добавление set
в map
. Разница очень существенна. Так как контейнеры обладают семантикой копирования, следующий код приведет к копированию всего набора s
в map
.set
// Заполнить s данными...
log_[id] = s; // Скопировать s и добавить его копию в log_
Это приведет к огромному числу дополнительных нежелательных копирований. Следовательно, общее правило при использовании контейнеров из контейнеров — это использовать
Глава 7
Алгоритмы
7.0. Введение
Эта глава рассказывает, как работать со стандартными алгоритмами и как использовать их для стандартных контейнеров. Эти алгоритмы первоначально являлись частью того, что часто называется Standard Template Library (STL — стандартная библиотека шаблонов) и представляет собой набор алгоритмов, итераторов и контейнеров, которые теперь вошли в стандартную библиотеку (глава 6 содержит рецепты по работе со стандартными контейнерами). Я их буду называть просто стандартными алгоритмами, итераторами и контейнерами, но не забывайте, что это то же самое, что другие авторы называют частью STL. Одним из базовых элементов стандартной библиотеки являются итераторы, так что первый рецепт описывает, что они собой представляют и как их использовать. После этого идет несколько рецептов, которые объясняют, как использовать и расширять стандартные алгоритмы. Наконец, если вы не нашли ничего подходящего в стандартной библиотеке, то рецепт 7.10 расскажет, как написать собственный алгоритм.
Представленные здесь рецепты в основном предназначены для работы со стандартными контейнерами, и тому есть две причины. Во-первых, стандартные контейнеры очень распространены, и лучше изучить стандарт, чем изобретать колесо. Во-вторых, реализация алгоритмов из стандартной библиотеки предоставляет хороший пример для подражания в смысле взаимодействия и производительности. Если вы посмотрите, как профессионалы выполнили код стандартной библиотеки, вы, скорее всего, узнаете много нового и полезного для себя.
Все стандартные алгоритмы используют итераторы. Даже если вы знакомы с концепцией итераторов, которые рассматриваются в первом рецепте, посмотрите на табл. 7.1, которая содержит перечень соглашений, используемых в остальных рецептах главы при демонстрации объявлений функций стандартных алгоритмов.