Итератор, возвращенный функцией end()
, указывает на следующую позицию за концом контейнера (или строки). Этот итератор обозначает несуществующий элемент за концом контейнера. Он используется как индикатор, означающий, что обработаны все элементы. Итератор, возвращенный функцией end()
, называют end
. Если контейнер пуст, функция begin()
возвращает тот же итератор, что и функция end()
.
Если контейнер пуст, возвращаемые функциями
begin()
и end()
итераторы совпадают и, оба являются итератором после конца.
Обычно точный тип, который имеет итератор, неизвестен (да и не нужен). В этом примере при определении итераторов b
и е
использовался спецификатор auto
(см. раздел 2.5.2). В результате тип этих переменных будет совпадать с возвращаемыми функциями-членами begin()
и end()
соответственно. Не будем пока распространяться об этих типах.
Итераторы поддерживают лишь несколько операций, которые перечислены в табл. 3.6. Два допустимых итератора можно сравнить при помощи операторов ==
и !=
. Итераторы равны, если они указывают на тот же элемент или если оба они указывают на позицию после конца того же контейнера. В противном случае они не равны.
Таблица 3.6. Стандартные операции с итераторами контейнера
*iter | Возвращает ссылку на элемент, обозначенный итератором iter |
iter->mem | Обращение к значению итератора iter и выборка члена mem основного элемента. Эквивалент (*iter).mem |
++iter | Инкремент итератора iter для обращения к следующему элементу контейнера |
--iter | Декремент итератора iter для обращения к предыдущему элементу контейнера |
iter1 == iter2 iter1 != iter2 | Сравнивает два итератора на равенство (неравенство). Два итератора равны, если они указывают на тот же элемент или на следующий элемент после конца того же контейнера |
Подобно указателям, к значению итератора можно обратиться, чтобы получить элемент, на который он ссылается. Кроме того, подобно указателям, можно обратиться к значению только допустимого итератора, который обозначает некий элемент (см. раздел 2.3.2). Результат обращения к значению недопустимого итератора или итератора после конца непредсказуем.
Перепишем программу из раздела 3.2.3, преобразующую строчные символы строки в прописные, с использованием итератора вместо индексирования:
string s("some string");
if (s.begin() != s.end()) { //
auto it = s.begin(); //
*it = toupper(*it); //
}
Как и в первоначальной программе, сначала удостоверимся, что строка s
не пуста. В данном случае для этого сравниваются итераторы, возвращенные функциями begin()
и end()
. Эти итераторы равны, если строка пуста. Если они не равны, то в строке s
есть по крайней мере один символ.
В теле оператора if
функция begin()
возвращает итератор на первый символ, который присваивается переменной it
. Обращение к значению этого итератора и передача его функции toupper()
позволяет перевести данный символ в верхний регистр. Кроме того, обращение к значению итератора it
слева от оператора присвоения позволяет присвоить символ, возвращенный функцией toupper()
, первому символу строки s
. Как и в первоначальной программе, вывод будет таким:
Some string
Итераторы используют оператор инкремента (оператор ++
) (см. раздел 1.4.1) для перемещения с одного элемента на следующий. Операция приращения итератора логически подобна приращению целого числа. В случае целых чисел результатом будет целочисленное значение на единицу больше 1
. В случае итераторов результатом будет перемещение итератора на одну позицию.
Поскольку итератор, возвращенный функцией
end()
, не указывает на элемент, он не допускает ни приращения, ни обращения к значению.
Перепишем программу, изменяющую регистр первого слова в строке, с использованием итератора.
//
//