Операции над отображениями и мультиотображениями. Функции получения итераторов

   
На этом шаге мы рассмотрим функции получения итераторов.

   
Отображения и мультиотображения не поддерживают прямой доступ к элементам, поэтому для обращения к элементам обычно используются итераторы.

   
Впрочем, у этого правила существует исключение: отображения поддерживают оператор индексирования [] для прямого обращения к
элементам. В таблице 1 перечислены стандартные функции получения итераторов, поддерживаемые отображениями и мультиотображениями.

Таблица 1. Операции получения итераторов для отображений и мультиотображений

ОперацияОписание
c.begin()Возвращает двунаправленный итератор для первого элемента (ключи считаются константными)
c.end()Возвращает двунаправленный итератор для позиции за последним элементом (ключи считаются константными)
c.rbegin()Возвращает обратный итератор для первого элемента при переборе в обратном направлении
c.rend()Возвращает обратный итератор для позиции за последним элементом при переборе в обратном направлении

   
Итераторы отображений и мультиотображений, как и во всех классах ассоциативных контейнеров, являются двунаправленными.
Такие итераторы не могут использоваться алгоритмами, рассчитанными на итераторы произвольного доступа (например, алгоритмами
сортировки или случайной перестановки элементов).

   
Но еще более важное ограничение заключается в том, что с точки зрения итератора все ключи элементов отображения или
мультиотображения считаются константными (то есть элемент интерпретируется как относящийся к типу pair<const key,T>).
Это необходимо для того, чтобы программа не могла нарушить упорядоченность элементов, изменяя их ключи. Однако в результате
для элементов отображения или мультиотображения вызов модифицирующих алгоритмов становится невозможным. Например,
удаление элементов не может осуществляться алгоритмом remove(), потому что "удаление" в действительности сводится к
перезаписи следующими элементами (данная тема подробно обсуждается на 108 шаге). Элементы
множеств и мультимножеств удаляются только функциями, предоставляемыми контейнером.

   
Пример использования итераторов:

  std::map<std::string,float> coll;
  std::map<std::string,float>::iterator pos; 
  for (pos = coll.begin(); pos != coll.end(); ++pos) {
    std::cout << "key: " << pos->first  << "\t"
    << "value: " << pos->second << std::endl; 
  }

   
Итератор pos используется для перебора в последовательности пар string/float. Выражение pos->flrst
определяет ключ элемента, а выражение pos->second - значение элемента.

   Замечание.
pos->first является сокращенной записью для (*pos).first. Некоторые старые библиотеки поддерживают только
полную форму записи.

   
Попытка изменения ключа приводит к ошибке:

  pos->first = "hello";   // ОШИБКА компипяции

   
Однако модификация значения элемента выполняется без проблем (при условии, что значение не принадлежит к константному типу):

  pos->second = 13.5;    // OK

   
Изменить ключ элемента можно только одним способом: заменить старый элемент новым элементом с тем же значением.
Унифицированная функция для выполнения этой операции выглядит так:

namespace MyLib {
  template <class Cont>
  inline
  bool replace_key (Cont& c,
                    const typename Cont::key_type& old_key, 
                    const typename Cont::key_type& new_key)
  {
    typename Cont::iterator pos; 
    pos = c.find(old_key); 
    if (pos != c.end()) {
      // Вставка нового элемента со значением старого элемента
      c.insert(typename Cont::value_type(new_key,pos->second));
      // Удаление старого элемента
      c.erase(pos);
      return true;
    } else 
    {
      // Ключ не найден
      return false;
    }
  }
}

   
Функции insert() и erase() описаны в следующем шаге.

   
При вызове этой унифицированной функции контейнеру просто передаются два ключа: старый и новый. Пример:

  std::map<std::string,float> coll;
  .   .   .   .   .
  MyLib::replace_key(coll,"old key","new key");

   
С мультиотображениями функция работает аналогично. Впрочем, отображения поддерживают более удобный способ
модификации ключа элемента. Вместо вызова replace_key() достаточно написать следующее:

  // Вставка нового элемента со значением старого элемента 
  coll["new_key"] = coll["old_key"];
  // Удаление старого элемента 
  coll.erase("old_key");

   
На следующем шаге мы рассмотрим вставку и удаление элементов.



Вы можете оставить комментарий, или Трекбэк с вашего сайта.

Оставить комментарий