Использование библиотеки STL

Ассоциативный контейнер map

Теперь мы можем перейти от set к map. «Введение в map для чайников» могло бы выглядеть следующим образом:

map<string, int> M;
M["One"] = 1;
M["Two"] = 2;
M["Many"] = 7;

int x = M["One"] + M["Two"];

if(M.find("Five") != M.end()) {
   M.erase("Five");
}

Очень просто, не так ли?

На самом деле, map очень похож на set, за исключением того, что вместо элементов map хранит пары элементов <ключ, значение>. Поиск при этом осуществляется только по ключу. Крайне приятно наличие оператора обращения по «индексу» (operator []).

Для того, чтобы просмотреть содержимое map, необходимо использовать итераторы. Удобнее всего это делать при помощи нашего макроса tr. Следует помнить, что итератор указывает не на элемент key, а на pair<key, value>:

map<string, int> M;
...
M["one"] = 1;
M["two"] = 2;
M["google"] = 1e100;
...
// найдём сумму всех значений --- т.е. всех правых частей 
// пар <string, int>
int r = 0;
tr(M, it) {
   r += it->second; 
   // (*it).first == [string], (*it).second == [int]
}
Как и в случае с set, элементы map хранятся упорядоченными по ключу. Поэтому не следует при работе с map::iterator модифицировать it->first: если вы нарушите правила упорядочивания элементов в map, за последствия никто отвечать не возьмётся.

В остальном контейнер map по интерфейсу практически эквивалентен контейнеру set.

Также важно помнить, что operator [] при обращении к несуществующему элементу в map создаст его. Новый элемент при этом будет инициализирован нулём (либо конструктором по умолчанию, если это не тривиальный тип данных). Данная особенность map может быть удобной, потому как выполнять операции с элементами можно не задумываясь об их присутствии в map. Существенным моментом является то, что operator [] не является константным (то есть может изменить объект, для которого вызван), поэтому им нельзя пользоваться, если map передан как const reference. Используйте map::find(element):

 
void f(const map<string, int>& M) {
   if(M["the meaning"] == 42) { 
     // Так нельзя! M передан как const reference
   }
   if(M.find("the meaning") != M.end() && 
                    M.find("the meaning")->second == 42) { 
      // А можно именно так
      cout << "Don't Panic!" << endl;
   }
}