operator[k]
возвращает ссылку на значение, ассоциированное с k
— независимо от того, существует ли k
в map
или нет. Если k
уже находится в map
, то возвращается ассоциированное с ним значение. Если нет, то k
вставляется, а затем используется конструктор по умолчанию, который создает объект значения для этого ключа. Чтобы сделать это более понятным, рассмотрим, что делает следующий код.
map<string, string> mapZipCodes; // Сейчас здесь ноль элементов
string myZip = mapZipCodes['Tempe']; // В map пока что нет элементов,
// но чему теперь равно count()?
Что находится в myZip
и сколько теперь элементов в mapZipCodes
? Так как operator[]
вставляет указанный ключ, если он не существует, myZip
содержит пустую строку, а в mapZipCodes
содержится один элемент. Это может оказаться нежелательно, но независимо от вашего желания помните, что operator[]
не является const
-методом: всегда есть вероятность того, что он изменит состояние map
, добавив узел.
Метод insert
предоставляет альтернативный метод добавления пар в отображение, insert
выполняет строгую вставку, а не вставку/обновление, как operator[]
. При использовании map (но не multimap
, который может содержать дублирующиеся ключи) insert
, если ключ уже существует, не делает ничего. По сравнению с ним operator[]
, если ключ уже существует, заменяет значение объекта для этого ключа на новое.
Но синтаксис вставки требует несколько большей работы, чем operator[]
, и он связан с тем, как map
хранит данные. Рассмотрим строку из примера 6.6.
strMap.insert(std::make_pair('Sunday', 'Sonntag'));
map
хранит пары ключ/значение в объекте pair
, pair
— это простой вспомогательный шаблон класса (объявленный в <utility>
и включенный в <map>
), который хранит два значения двух типов. Чтобы объявить pair
из двух string
, сделайте так.
pair<string, string> myPair;
Первый и второй элементы в pair
доступны по открытым членам first
и second
. При использовании для доступа к элементам map
оператора operator[]
обычно работать с pair
не приходится, но в случае со многими другими методами это придется делать, так что следует знать, как создавать и использовать объекты pair
. Например, итераторы разыменовываются в простые объекты pair
, так что при их использовании, как это делается в примере 6.6, следует знать, как получить ключ и его значение.
for (map<string, string> iterator p = strMap.begin();
p != strMap.end(); ++p)
cout << 'English: ' << p->first
<< ', German: ' << p->second << endl;
Ключ хранится в first
, а значение хранится в second
.
Однако это не объясняет, почему я использовал make_pair
. make_pair
— это вспомогательный шаблон функции, который создает объект pair
на основе двух переданных в него аргументов. Некоторые предпочитают этот подход вызову конструктора pair
, так как шаблон класса не может догадаться о типах своих аргументов, в то время как шаблон функции может. Таким образом, эти две строки кода функционально эквивалентны.
strMap.insert(std::make_pair('Sunday', 'Sonntag'));
strMap.insert(std::pair<string, string>('Sunday', 'Sonntag'));
map
не допускает наличия дублирующихся ключей. Если требуется разрешить дублирование ключей, следует использовать multimap
, который является map
, разрешающим наличие несколько одинаковых ключей. Его интерфейс идентичен map
, но поведение методов в необходимых случаях отличается. В табл. 6.1 приведен перечень методов, которые есть в одном, но отсутствуют в другом, и пояснения различий в поведении общих методов, map и multimap
содержат несколько typedef
, которые описывают различные значения, хранящиеся в них. В табл. 6.1 они используются следующим образом:
key_type
Это тип ключа. В string map,
объявленном как map<string, MyClass*>
, key_type
должен быть string
.
mapped_type
Это тип значения, на которое отображается ключ. В string map
, объявленном как map<string, MyClass*>
, mapped_type
должен быть MyClass*
.
value_type
Это тип объекта, содержащего ключ и значение, которой, применительно к map
и multimap
, является pair<const key_type, mapped_type>
.
Метод | map, multimap или оба | Поведение |
---|---|---|
T& operator[] (const key_type& k) | map | Возвращает ссылку на объект значения, сохраненный с ключом k . Если k в map отсутствует, то он добавляется, а объект значения создается с помощью конструктора по умолчанию |
iterator insert(const value_type& v) pair<iterator, bool> insert (const value_type& v) | Оба | Первая версия вставляет v в multimap и возвращает итератор, который указывает на вставленную пару pair . Вторая версия вставляет v и map при условии, что в map еще не содержится ключа, равного v . Возвращаемая pair содержит итератор который указывает на вставленную pair , если произошла вставка, и bool , указывающий, была ли вставка успешной |
iterator find(const key_type& k) | Оба | Возвращает итератор или const_iterator , который указывает на mapped_type , соответствующий k . В multimap не гарантируется, что возвращаемый итератор будет указывать на первое значение, соответствующее k . Если ключа, равного k, нет, то возвращаемый итератор равен end() |
Также табл 6.1 показывает разницу в поведении между map
и