Итератор, возвращенный функцией 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(), не указывает на элемент, он не допускает ни приращения, ни обращения к значению.
Перепишем программу, изменяющую регистр первого слова в строке, с использованием итератора.
//
//