Термин iterator
, определенном классом контейнера, или об объекте итератора.
Следует уяснить, что существует целый набор типов, связанных концептуально. Тип относится к итераторам, если он поддерживает общепринятый набор функций. Эти функции позволяют обращаться к элементу в контейнере и переходить с одного элемента на другой.
Каждый класс контейнера определяет тип по имени iterator
, который обеспечивает действия концептуального итератора.
begin()
и end()
Тип, возвращаемый функциями begin()
и end()
, зависит от константности объекта, для которого они были вызваны. Если объект является константой, то функции begin()
и end()
возвращают итератор типа const_iterator
; если объект не константа, они возвращают итератор типа iterator
.
vector
const vector
auto it1 = v.begin(); //
auto it2 = cv.begin(); //
const_iterator
), когда необходимо только читать, но не записывать в объект. Чтобы позволить специально задать тип const_iterator
, новый стандарт вводит две новые функции, cbegin()
и cend()
:
auto it3 = v.cbegin(); //
Подобно функциям-членам begin()
и end()
, эти функции-члены возвращают итераторы на первый и следующий после последнего элементы контейнера. Но независимо от того, является ли вектор (или строка) константой, они возвращают итератор типа const_iterator
.
При обращении к значению итератора получается объект, на который указывает итератор. Если этот объект имеет тип класса, то может понадобиться доступ к члену полученного объекта. Например, если есть вектор строк, то может понадобиться узнать, не пуст ли некий элемент. С учетом, что it
— это итератор данного вектора, можно следующим образом проверить, не пуста ли строка, на которую он указывает:
(*it).empty()
По причинам, рассматриваемым в разделе 4.1.2, круглые скобки в части (*it).empty()
необходимы. Круглые скобки требуют применить оператор обращения к значению к итератору it
, а к результату применить точечный оператор (см. раздел 1.5.2). Без круглых скобок точечный оператор относился бы к итератору it
, а не к полученному объекту.
(*it).empty() //
//
*it.empty() //
//
//
Второе выражение интерпретируется как запрос на выполнение функции-члена empty()
объекта it
. Но it
— это итератор, и он не имеет такой функции. Следовательно, второе выражение ошибочно.
Чтобы упростить такие выражения, язык предоставляет ->
). Оператор стрелки объединяет обращение к значению и доступ к члену. Таким образом, выражение it->mem
является синоним выражения (*it).mem
.
Предположим, например, что имеется вектор vector
по имени text
, содержащий данные из текстового файла. Каждый элемент вектора — это либо предложение, либо пустая строка, представляющая конец абзаца. Если необходимо отобразить содержимое первого параграфа из вектора text
, то можно было бы написать цикл, который перебирает вектор text
, пока не встретится пустой элемент.
//
for (auto it = text.cbegin();
it != text.cend() && !it->empty(); ++it)
cout << *it << endl;