6.12.1. Определение объекта map и заполнение его элементами
Чтобы определить объект класса map, мы должны указать, как минимум, типы ключа и значения. Например:
mapstring,int word_count;
Здесь задается объект word_count типа map, для которого ключом служит объект типа string, а ассоциированным с ним значением – объект типа int. Аналогично
class employee;
mapint,employee* personnel;
определяет personnel как отображение ключа типа int (уникальный номер служащего) на указатель, адресующий объект класса employee.
Для нашей поисковой системы полезно такое отображение:
typedef pairshort,short location;
typedef vectorlocation loc;
mapstring,loc* text_map;
Поскольку имевшийся в нашем распоряжении компилятор не поддерживал аргументы по умолчанию для параметров шаблона, нам пришлось написать более развернутое определение:
mapstring,loc*, // ключ, значение
lessstring, // оператор сравнения
allocator // распределитель памяти по умолчанию
text_map;
По умолчанию сортировка ассоциативных контейнеров производится с помощью операции “меньше”. Однако можно указать и другой оператор сравнения (см. раздел 12.3 об объектах-функциях).
После того как отображение определено, необходимо заполнить его парами ключ/значение. Интуитивно хочется написать примерно так:
#include map
#include string
mapstring,int word_count;
word_count[ string("Anna") ] = 1;
word_count[ string("Danny") ] = 1;
word_count[ string("Beth") ] = 1;
// и так далее ...
Когда мы пишем:
word_count[ string("Anna") ] = 1;
на самом деле происходит следующее:
* Безымянный временный объект типа string инициализируется значением "Anna" и передается оператору взятия индекса, определенному в классе map.
* Производится поиск элемента с ключом "Anna" в массиве word_count. Такого элемента нет.
* В word_count вставляется новая пара ключ/значение. Ключом является, естественно, строка "Anna". Значением – 0, а не 1.
* После этого значению присваивается величина 1.
Если элемент отображения вставляется в отображение с помощью операции взятия индекса, то значением этого элемента становится значение по умолчанию для его типа данных. Для встроенных арифметических типов – 0.
Следовательно, если инициализация отображения производится оператором взятия индекса, то каждый элемент сначала получает значение по умолчанию, а затем ему явно присваивается нужное значение. Если элементы являются объектами класса, у которого инициализация по умолчанию и присваивание значения требуют больших затрат времени, программа будет работать правильно, но недостаточно эффективно.
Для вставки одного элемента предпочтительнее использовать следующий метод:
// предпочтительный метод вставки одного элемента
word_count.insert(
mapstring,i nt::
value_type( string("Anna"), 1 )
);
В контейнере map определен тип value_type для представления хранимых в нем пар ключ/значение. Строки
map string,int ::
value_type( string("Anna"), 1 )
создают объект pair, который затем непосредственно вставляется в map. Для удобства чтения можно использовать typedef:
typedef mapstring,int::value_type valType;
Теперь операция вставки выглядит проще:
word_count.insert( valType( string("Anna"), 1 ));
Чтобы вставить элементы из некоторого диапазона, можно использовать метод insert(), принимающий в качестве параметров два итератора. Например:
map string, int word_count;
// ... заполнить
map string,int word_count_two;
// скопируем все пары ключ/значение
word_count_two.insert(word_count.begin(),word_count.end());
Мы могли бы сделать то же самое, просто проинициализировав одно отображение другим:
// инициализируем копией всех пар ключ/значение
map string, int word_count_two( word_count );