Я считаю, что обычным ответом на это будет «нет», поскольку итератор end()
для контейнеров представляет собой адрес «за концом», который является неопределенным поведением для разыменования. Я не могу найти явного утверждения в стандарте, которое освобождает строки от этого ограничения, хотя строки имеют особый случай по сравнению с другими контейнерами.
Стандарт C ++ 11 заявляет, что вы можете прочитать один индекс после конец строки. string[size()]
ссылается на доступное только для чтения значение нулевого терминатора.
24.3.2.5 доступ к элементу basic_string [string.access]
const_reference operator[](size_type pos) const;
reference operator[](size_type pos);
(1) Требуется: pos <= size()
.
(2) Возвращает: *(begin() + pos) if pos < size()
. В противном случае возвращает ссылку на объект типа charT
со значением charT()
, где изменение объекта на любое значение, отличное от charT()
, приводит к неопределенному поведению.
front()
определяется чтобы быть эквивалентным return operator[](0)
, что эквивалентно return operator[](size())
для пустой строки.
end() - begin()
четко определено как разница длины строки, поэтому end()
должно указывать с индексом size()
для разумной реализации, чтобы определить эту арифметику c.
В приведенном выше стандартном отрывке operator[](pos)
эквивалентно *(begin() + pos)
if pos < size()
. не говорит, что вы можете разыменовать begin() + size()
, но считаете ли вы разумным предположить, что это должно быть четко определено? Или еще лучше, знаете ли вы какое-либо доказательство, освобождающее строковые итераторы от ограничения?
Кроме того, можно ли доказать, что *(begin() + i)
для любого i
эквивалентно operator[](i)
?