Цитирование из последнего проекта доступны в Интернете.
[iterator.requirements.general]/7
Так же, как обычный указатель на массив гарантирует, что существует значение указателя, указывающее на последний элемент массива, так и для любого типа итератора есть значение итератора, которое указывает за последним элементом соответствующей последовательности. Эти значения называются прошлыми значениями. Значения итератора i
, для которых определено выражение *i
, называются разыменованными. Библиотека никогда не предполагает, что значения конца-в-конце являются разыменованными.
Я считаю, что это относится не только к end()
, но и к тому, что последует за этим. Обратите внимание, что в стандарте четко не указано, что end()
никогда не следует разыменовывать.
И Cpp17Iterator requirements table
гласит, что для выражения *r
, r
должно быть разыменовано:
Итератор конца-в-конце считается итератором без приращения, и его увеличение (как вы делаете в начале цикла while
) приводит к неопределенному поведению.
При использовании std::advance
может произойти нечто подобное тому, что вы пытаетесь сделать.
В книге «Стандартная библиотека C ++: учебное пособие и справочник» Николая Йозуттиса есть цитата:
Обратите внимание, что advance()
не проверяет, пересекает ли он end()
последовательности (он не может проверить, потому что итераторы в общем случае не знают контейнеры, с которыми они работают). Таким образом, вызов этой функции может привести к неопределенному поведению, поскольку вызывающий оператор ++
для конца последовательности не определен.