Оператор if проверяет логическую часть возвращаемого значения. Если это значение false, то вставка не произошла. Следовательно, слово уже было в карте word_count, поэтому следует увеличить значение связанного с ним счетчика.

Еще раз о синтаксисе

Оператор приращения счетчика в этой версии программы подсчета слов трудно понять. Разобрать это выражение будет существенно проще, если сначала расставить скобки в соответствии с приоритетом (см. раздел 4.1.2) операторов:

++((ret.first)->second); // эквивалентное выражение

Рассмотрим это выражение поэтапно.

• ret — пара, содержащая значение, возвращаемое функцией insert().

• ret.first — первая переменная-член пары, на которую указывает итератор карты, с данным ключом.

• ret.first-> — обращение к значению итератора, позволяющее получить этот элемент. Элементы карты также являются парами.

• ret.first->second — та часть пары элемента карты, которая является значением.

• ++ret.first->second — инкремент этого значения.

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

Для читателей, использующих устаревший компилятор или код, предшествующий новому стандарту, объявление и инициализация пары ret также не совсем очевидны:

pair::iterator, bool> ret =

 word_count.insert(make_pair(word, 1));

Здесь определяется пара, вторая переменная-член которой имеет тип bool. Понять тип первой переменной-члена этой пары немного труднее. Это тип итератора, определенный типом map.

Добавление элементов в контейнеры multiset и multimap

Работа программы подсчета слов зависит от того факта, что каждый ключ может присутствовать только однажды. Таким образом, с любым словом будет связан только один счетчик. Но иногда необходима возможность добавить дополнительные элементы с тем же ключом. Например, могло бы понадобиться сопоставить авторов с названиями написанных ими книг. В данном случае для каждого автора могло бы быть несколько записей, поэтому будет использован контейнер multimap, а не map. Поскольку ключи контейнеров multi не должны быть уникальным, функция insert() для них всегда вставляет элемент:

multimap authors;

// добавляет первый элемент с ключом Barth, John

authors.insert({"Barth, John", "Sot-Weed Factor"});

// ok: добавляет второй элемент с ключом Barth, John

authors.insert({"Barth, John", "Lost in the Funhouse"});

У контейнеров, допускающих совпадение ключей, функция insert() получает один элемент и возвращает итератор на новый элемент. Нет никакой необходимости возвращать логическое значение, поскольку в эти контейнеры функция insert() всегда добавляет новый элемент.

Упражнения раздела 11.3.2

Упражнение 11.20. Перепишите программу подсчета слов из раздела 11.1 так, чтобы использовать функцию insert() вместо индексации. Какая версия программы по-вашему проще? Объясните почему.

Упражнение 11.21. С учетом того, что word_count является картой типов string и size_t, а также того, что word имеет тип string, объясните следующий цикл:

while (cin >> word)

 ++word_count.insert({word, 0}).first->second;

Упражнение 11.22. С учетом, что map>, напишите типы, используемые как аргументы, и возвращаемое значение версии функции insert(), вставляющей один элемент.

Упражнение 11.23. Перепишите карту, хранящую вектора имен детей с ключом в виде фамилии семьи из упражнений раздела 11.2.1, так, чтобы использовался контейнер multimap.

<p>11.3.3. Удаление элементов</p>

Ассоциативные контейнеры определяют три версии функции erase(), описанные в табл. 11.5. Подобно последовательным контейнерам, можно удалить один элемент или диапазон элементов, передав функции erase() итератор или пару итераторов. Эти версии функции erase() подобны соответствующим функциям последовательных контейнеров: указанный элемент (элементы) удаляется и возвращается тип void.

Таблица 11.5. Удаление элементов ассоциативного контейнера

Перейти на страницу:

Похожие книги