C++. Сборник рецептов
Шрифт:
Метод
insert
предоставляет альтернативный метод добавления пар в отображение, insert
выполняет строгую вставку, а не вставку/обновление, как operator[]
. При использовании map (но не multimap
, который может содержать дублирующиеся ключи) insert
, если ключ уже существует, не делает ничего. По сравнению с ним operator[]
, если ключ уже существует, заменяет значение объекта для этого ключа на новое. Но синтаксис вставки требует несколько большей работы, чем
operator[]
, и он связан с тем, как map
хранит данные. Рассмотрим строку из примера 6.6. strMap.insert(std::make_pair("Sunday", "Sonntag"));
ma
p
хранит пары ключ/значение
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>
. Табл. 6.1. map и multimap
Метод | map, multimap или оба | Поведение |
---|---|---|
T& operator[] (const key_type& k) | map | Возвращает ссылку на объект значения, сохраненный с ключом k . Если k
|
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
и multimap
. Если
operator[]
вам не подходит, т.е. другой способ найти ключ в map
. Для этого можно использовать метод find
. map<string, string>::const_iterator p
= strMap.find("Thursday");
if (p != strMap.end)
cout << "Thursday = " << p->second << endl;
Но не забудьте, что при использовании
multimap
не гарантируется, что возвращаемый элемент будет первым элементом с ключом, равным искомому. Если нужен первый элемент, чей ключ не меньше определенного значения или не больше определенного значения, используйте lower_bound
или upper_bound
. lower_bound
возвращает итератор, указывающий на первую пару ключ/значение, равную или большую, чем аргумент key_type
. Другими словами, если ваш map
содержит дни недели, как в примере 6.6, следующий код вернет итератор, который указывает на пару, содержащую "Friday"
и "Freitag"
. p = strMap.lower_bound("Foo");
if (p != strMap.end)
cout << p->first << " = " << p->second << endl;
Это происходит благодаря тому, что первый ключ больше или равен
"Foo"
. upper_bound
работает аналогично, но с противоположным условием. В начале этого обсуждения я упоминал, что элементы в map хранятся в отсортированном по ключам порядке, так что при переборе от
begin
до end
каждый элемент будет «больше», чем предшествующий (а в multimap
— больше или равен ему) Но при использовании более сложных ключей, чем string
или числа, может потребоваться указать, как при вставке элементов в отображение следует сравнивать ключи. По умолчанию ключи хранятся с помощью стандартного функтора
less
(объявленного в <functional>
). less
— это двоичная функция (принимает два аргумента одинакового типа), которая возвращает bool
, указывающий на то, больше ли первый аргумент, чем второй, или нет. Другими словами, less(a, b)
возвращает a < b
. Если это не то, что вам требуется, создайте свой собственный функтор и объявите map
с его помощью. Например, если в качестве ключа используется объект Person
и каждый Person
имеет имя и фамилию, то может потребоваться сравнивать фамилии и имена. Пример 6.7 показывает способ сделать это.
Поделиться:
Популярные книги
Лишняя дочь
Любовные романы:
любовно-фантастические романы
8.22
рейтинг книги
Маверик
4. Сопряжение
Фантастика:
боевая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Мужчина моей судьбы
2. Мужчина не моей мечты
Любовные романы:
любовно-фантастические романы
8.03
рейтинг книги
Развод, который ты запомнишь
1. Развод
Любовные романы:
остросюжетные любовные романы
короткие любовные романы
5.00
рейтинг книги
Кодекс Охотника. Книга XIV
14. Кодекс Охотника
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Столкновение
1. Вне льда
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Черный маг императора
1. Черный маг императора
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга V
5. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Любимая учительница
1. совершенная любовь
Любовные романы:
современные любовные романы
эро литература
8.73
рейтинг книги
Адвокат империи
1. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
фэнтези
5.75
рейтинг книги
Боярышня Дуняша 2
2. Боярышня
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Убивать чтобы жить 9
9. УЧЖ
Фантастика:
героическая фантастика
боевая фантастика
рпг
5.00
рейтинг книги
Новый Рал 7
7. Рал!
Фантастика:
попаданцы
5.00
рейтинг книги
Боги, пиво и дурак. Том 3
3. Боги, пиво и дурак
Фантастика:
фэнтези
попаданцы
5.00