#include <string>
#include <iostream>
int main() {
std::string s = "abcdef";
std::string s2 = s;
auto begin = const_cast<std::string const &>(s2).begin();
auto end = s2.end();
std::cout << end - begin << '\n';
}
Этот код смешивает результат begin() const
с результатом end()
. Ни одна из этих функций не может делать недействительными какие-либо итераторы. Однако мне любопытно, действительно ли требование end()
не аннулировать переменную итератора begin
означает, что переменная begin
может использоваться с end
.
Рассмотрим C ++ 98, реализацию std::string
с функцией копирования при записи; неконстантные функции begin()
и end()
вызывают копирование внутреннего буфера, потому что результат этих функций может использоваться для изменения строки. Таким образом, begin
, приведенный выше, начинает действовать как для s
, так и для s2
, но использование неконстантного члена end()
приводит к тому, что он больше не действует для s2
, контейнера, который его создал.
Приведенный выше код дает «неожиданные» результаты с реализацией копирования при записи, такой как libstdc ++. Вместо end - begin
, совпадающего с s2.size()
, libstdc ++ производит другое число.
Означает ли то, что
begin
больше не является действительным итератором вs2
, контейнере, из которого он был получен, «аннулирует» итератор? Если вы посмотрите на требования к итераторам, все они, похоже, соблюдаются для этого итератора после вызова.end()
, поэтому, возможно,begin
по-прежнему квалифицируется как действительный итератор и, следовательно, не был признан недействительным?Хорошо ли определен приведенный выше код в C ++ 98? Что в C ++ 11 запрещает реализации копирования при записи?
Судя по моему собственному краткому чтению спецификаций, он кажется недостаточно определенным, так что не может быть никакой гарантии, что результаты begin()
и end()
могут когда-либо использоваться вместе, даже без смешивания версий с константой и неконстантой.
6
, но, очевидно, нет. Реализация COW несовместима. - person Lightness Races in Orbit   schedule 26.02.2015