Язык программирования C++.

11.3.4. Индексация карт.

Контейнеры map и unordered_map предоставляют оператор индексирования и соответствующую функцию at() (см. раздел 9.3.2), представленные в табл. 11.6. Типы контейнеров set не поддерживают индексацию, поскольку в наборе нет никакого "значения", связанного с ключом. Элементы сами являются ключами, поэтому операция "доступа к значению, связанному с ключом", бессмысленна. Нельзя индексировать контейнер multimap или unordered_multimap, поскольку с заданным ключом может быть ассоциировано несколько значений.

Таблица 11.6. Операторы индексирования контейнеров map и unordered_map

c[k] Возвращает элемент с ключом k; если ключа k нет в контейнере с, добавляется новый элемент, инициализированный значением с ключом k
c.at(k) Проверяет наличие элемента с ключом k; если его нет в контейнере с, передает исключение out_of_range (см. раздел 5.6)

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

Рассмотрим следующий код:

map <string, size_t> word_count; // пустая карта

// вставить инициализированный значением по умолчанию элемент

// с ключом Anna; а затем установить для него значение 1

word_count["Anna"] = 1;

Ниже приведена имеющая место последовательность действий.

• В контейнере word_count происходит поиск элемента с ключом Anna. Элемент не найден.

• В контейнер word_count добавляется новая пара ключ-значение. Ключ (константная строка) содержит текст Anna. Значение инициализируется по умолчанию, в данном случае нулем.

• Вновь созданному элементу присваивается значение 1.

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

Язык программирования C++.Индексация карт существенно отличается от индексации массивов или векторов: использование отсутствующего ключа приводит к добавлению элемента с таким ключом в карту.

Использование значения, возвращенного оператором индексирования.

Иной способ индексирования карт, отличающий его от других использованных ранее операторов индексирования, влияет на тип возвращаемого значения. Обычно тип, возвращенный в результате обращения к значению итератора, и тип, возвращенный оператором индексирования, совпадают. У карт все не так: при индексировании возвращается объект типа mapped_type, а при обращении к значению итератора карты — объект типа value_type (см. раздел 11.3).

Общим у всех операторов индексирования является то, что они возвращают l-значение (см. раздел 4.1.1). Поскольку возвращается l-значение, возможно чтение и запись в элемент:

cout << word_count["Anna"]; // получить элемент по индексу Anna;

                            // выводит 1

++word_count["Anna"];       // получить элемент и добавить к нему 1

cout << word_count["Anna"]; // получить элемент и вывести его;

                            // выводит 2

Язык программирования C++.В отличие от вектора или строки, тип данных, возвращаемых оператором индексирования карты, отличается из типа, полученного при обращении к значению итератора карты.

Тот факт, что индексирование добавляет элемент, если карта его еще не содержит, позволяет создавать удивительно сжатый код, такой как цикл в программе подсчета слов (см. раздел 11.1). С другой стороны, иногда необходимо только узнать, присутствует ли элемент, но не добавлять его в случае отсутствия. В таких случаях не следует использовать оператор индексирования.

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

Упражнение 11.24. Что делает следующая программа?

map<int, int> m;

m[0] = 1;

Упражнение 11.25. Сравните следующую программу с предыдущей:

vector<int> v;

v[0] = 1;

Упражнение 11.26. Какой тип применяется при индексировании карты? Какой тип возвращает оператор индексирования? Приведите конкретный пример, т.е. создайте карту, используйте типы, которые применимы для ее индексирования, а затем выявите типы, которые будет возвращать оператор индексирования.