Чтение онлайн

на главную - закладки

Жанры

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
в 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
и
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 показывает способ сделать это.

Поделиться:
Популярные книги

Идеальный мир для Лекаря 27

Сапфир Олег
27. Лекарь
Фантастика:
аниме
фэнтези
5.00
рейтинг книги
Идеальный мир для Лекаря 27

Идеальный мир для Лекаря 15

Сапфир Олег
15. Лекарь
Фантастика:
боевая фантастика
юмористическая фантастика
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 15

Князь Мещерский

Дроздов Анатолий Федорович
3. Зауряд-врач
Фантастика:
альтернативная история
8.35
рейтинг книги
Князь Мещерский

Ты нас предал

Безрукова Елена
1. Измены. Кантемировы
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Ты нас предал

Бракованная невеста. Академия драконов

Милославская Анастасия
Фантастика:
фэнтези
сказочная фантастика
5.00
рейтинг книги
Бракованная невеста. Академия драконов

Чужая семья генерала драконов

Лунёва Мария
6. Генералы драконов
Фантастика:
фэнтези
5.00
рейтинг книги
Чужая семья генерала драконов

Истребители. Трилогия

Поселягин Владимир Геннадьевич
Фантастика:
альтернативная история
7.30
рейтинг книги
Истребители. Трилогия

Любовь Носорога

Зайцева Мария
Любовные романы:
современные любовные романы
9.11
рейтинг книги
Любовь Носорога

Курсант: Назад в СССР 10

Дамиров Рафаэль
10. Курсант
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Курсант: Назад в СССР 10

Прорвемся, опера! Книга 2

Киров Никита
2. Опер
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Прорвемся, опера! Книга 2

Газлайтер. Том 2

Володин Григорий
2. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 2

Камень. Книга пятая

Минин Станислав
5. Камень
Фантастика:
боевая фантастика
6.43
рейтинг книги
Камень. Книга пятая

Попаданка в академии драконов 2

Свадьбина Любовь
2. Попаданка в академии драконов
Любовные романы:
любовно-фантастические романы
6.95
рейтинг книги
Попаданка в академии драконов 2

Камень. Книга 4

Минин Станислав
4. Камень
Фантастика:
боевая фантастика
7.77
рейтинг книги
Камень. Книга 4