Как известно, каждый стандартный контейнер поддерживает четыре типа итераторов. Для контейнера container
Рассмотрим несколько сигнатур insert и erase в контейнере vector
iterator insert(iterator position, const T& x);
iterator erase (iterator position);
iterator erase ( iterator rangeBegin, iterator rangeEnd);
Аналогичные функции имеются у всех стандартных контейнеров, но тип возвращаемого значения определяется типом контейнера. Обратите внимание: перечисленные функции требуют передачу параметров типа iterator.
Не const_iterator
, не reverse_iterator
и не const_reverse_iterator
— только iterator
. Хотя контейнеры поддерживают четыре типа итераторов, один из этих типов обладает привилегиями, отсутствующими у других типов. Тип iterator
занимает особое место.
На следующей диаграмме показаны преобразования, возможные между итераторами разных типов.
Из рисунка следует, что iterator
преобразуется в const_iterator
и reverse_ iterator
, а reverse_iterator
— в const_reverse_iterator
. Кроме того, reverse_iterator преобразуется в iterator при помощи функции base типа reverse_iterator, a const_ reverse_iterator аналогичным образом преобразуется в const_iterator. Однако из рисунка не видно, что итераторы, полученные при вызове base, могут оказаться не теми, которые вам нужны. За подробностями обращайтесь к совету 28.
Обратите внимание: не существует пути от const_iterator
к iterator
или от const_reverse_iterator
к reverse_iterator
. Из этого важного обстоятельства следует, что const_iterator
и const_reverse_iterator могут вызвать затруднения с некоторыми функциями контейнеров. Таким функциям необходим тип iterator, а из-за отсутствия обратного перехода от const-итераторов к iterator первые становятся в целом бесполезными, если вы хотите использовать их для определения позиции вставки или удаления элементов.
Однако не стоит поспешно заключать, что const-итераторы вообще бесполезны. Это не так. Они прекрасно работают с алгоритмами, поскольку для алгоритмов обычно подходят все типы итераторов, относящиеся к нужной категории. Кроме того, const-итераторы подходят для многих функций контейнеров. Проблемы возникают лишь с некоторыми формами insert и erase.
Обратите внимание на формулировку: const-итераторы становятся
•Некоторым версиям insert и erase при вызове должен передаваться тип iterator. Const- и reverse-итераторы им не подходят.
•Автоматическое преобразование const-итератора в iterator невозможно, а методика получения iterator на основании const_iterator (совет 27) применима не всегда, да и эффективность ее не гарантируется.
•Преобразование reverse_iterator в iterator может требовать дополнительной регулировки итератора. В совете 28 рассказано, когда и почему возникает такая необходимость.
Из сказанного следует однозначный вывод: если вы хотите работать с контейнерами просто и эффективно и по возможности застраховаться от нетривиальных ошибок, выбирайте iterator вместо его cons