Подтвердить что ты не робот

Классификация входных итераторов

Я читал книгу Стэнли Липпмана "С++ Primer", чтобы узнать больше о С++ 11.

В главе "Общие алгоритмы" он упоминает, что итераторы, используемые в общих алгоритмах, можно разделить на 5 типов на основе поддерживаемых ими операций: итераторы ввода, итераторы вывода, итераторы пересылки, двунаправленные итераторы и итераторы произвольного доступа.

Цитата из его книги:

Итераторы ввода могут считывать элементы в последовательности. Они должны обеспечить следующие операторы - равенство (==), неравенство (!=), разыменование (*), postfix & приращение префикса (++) и оператор стрелки (->). вход итераторы могут использоваться только последовательно. Мы гарантируем, что *it++ действителен, но приращение ввода-итератора может привести к аннулированию всех других итераторов в этом потоке. В результате нет никакой гарантии, что мы можем сохранить состояние входного итератора и исследовать элемент через этот сохраненный итератор

Мне трудно понять цитату жирным шрифтом. Почему приращение итератора ввода, предназначенного только для чтения элементов, делает недействительными другие итераторы? Почему мы не можем сохранить состояние ввода-итератора?

4b9b3361

Ответ 1

Пример может проиллюстрировать это:

Предположим, что у вас есть поток с (крошечным) внутренним буфером и итератором ввода, ссылающимся на этот буфер. Если вы увеличиваете входной итератор, все сохраненные итераторы ввода, ссылаясь на этот буфер, станут недействительными, как только буфер потока получит новое содержимое (underflows).

Относительно комментария:

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

Ответ 2

Итератор ввода может ссылаться на все, что моделирует входной поток, который включает в себя:

  • файл на физическом диске
  • ввод текста на клавиатуре человека
  • байты, отправленные по сетевому соединению

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

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

Ответ 3

Как правило, входные итераторы не имеют базового контейнера в Память. Классическим примером является std::istream_iterator. Когда вы увеличиваете один из итераторов, вы на самом деле продвигаетесь вперед базовая внешняя последовательность (файл), что означает, что другие итераторы этой последовательности также изменяются.