Читаем Программирование полностью

  typedef sometype2 const_iterator;


  iterator begin();      // указывает на первый элемент

  iterator end();        // указывает на следующий за последним

                         // элемент

  Value& operator[](const Key& k); // индексирование

                                   // по переменной k

  iterator find(const Key& k);     // поиск по ключу k

  void erase(iterator p);          // удаление элемента, на который

                                   // указывает итератор p

  pair insert(const value_type&);

  // вставляет пару (key,value)

  // ...

};


Настоящий вариант контейнера определен в заголовке . Можно представить себе итератор в виде указателя Node*, но при реализации итератора нельзя полагаться на какой-то конкретный тип.

Сходство интерфейсов классов vector и list (см. разделы 20.5 и B.4) очевидно. Основное отличие заключается в том, что при перемещении по контейнеру элементами теперь являются пары типа pair. Этот тип является очень полезным в библиотеке STL.


template struct pair {

  typedef T1 first_type;

  typedef T2 second_type;

  T1 first;

  T2 second;


  pair():first(T1()),second(T2()) { }

  pair(const T1& x,const T2& y):first(x),second(y) { }

  template

    pair(const pair& p):first(p.first), second(p.second) { }

};


template pair make_pair(T1 x, T2 y)

{

  return pair(x,y);

}


Мы скопировали полное определение класса pair и его полезную вспомогательную функцию make_pair() из стандарта.

  При перемещении по контейнеру map элементы перебираются в порядке, определенном ключом. Например, если мы перемещаемся по контейнеру, описанному в примере, то получим следующий порядок обхода:


(Apple,7) (Grape,2345) (Kiwi,100) (Orange,99) (Plum,8) (Quince,0)


Порядок вставки узлов значения не имеет.

Операция insert() имеет странное возвращаемое значение, которое в простых программах, как правило, мы игнорируем. Это пара, состоящая из итератора, установленного на пару (ключ, значение), и переменной типа bool, принимающей значение true, если данная пара (ключ, значение) была вставлена с помощью вызова функции insert(). Если ключ уже был в контейнере, то вставка игнорируется и значение типа bool принимает значение false.

  Мы можем определить порядок обхода ассоциативного массива с помощью третьего аргумента (предикат Cmp в объявлении класса map). Рассмотрим пример.


map m;


Предикат No_case определяет сравнение символов без учета регистра (см. раздел 21.8). По умолчанию порядок обхода определяется предикатом less, т.е. отношением “меньше”. 

21.6.3. Еще один пример ассоциативного массива

Для того чтобы оценить полезность контейнера map, вернемся к примеру с индексом Доу–Джонс из раздела 21.5.3. Описанный там код работает правильно, только если все веса записаны в объекте класса vector в тех же позициях, что и соответствующие имена. Это требование носит неявный характер и легко может стать источником малопонятных ошибок. Существует много способов решения этой проблемы, но наиболее привлекательным является хранение всех весов вместе с их тикером, например (“AA”,2.4808). Тикер — это аббревиатура названия компании. Аналогично тикер компании можно хранить вместе с ценой ее акции, например (“AA”,34.69). В заключение для людей, редко сталкивающихся с фондовым рынком США, мы можем записывать тикер вместе с названием компании, например (“AA”,“Alcoa Inc.”); иначе говоря, можем хранить три аассоциативных массива соответствующих значений.

Сначала создадим ассоциативный контейнер, содержащий пары (символ,цена).


map dow_price;

  // Индекс Доу - Джонса (символ, цена);

  // текущие котировки см. на веб-сайте www.djindexes.com

dow_price["MMM"] = 81.86;

dow_price ["AA"] = 34.69;

dow_price ["MO"] = 54.45;

// ...


Ассоциативный массив, содержащий пары (символ, вес), объявляется так:


map dow_weight; // Индекс Доу-Джонса (символ, вес)

dow_weight.insert(make_pair("MMM", 5.8549));

dow_weight.insert(make_pair("AA",2.4808));

dow_weight.insert(make_pair("MO",3.8940));

// ...


Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже