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

Недействительность прошедшего итератора на С++ 11

Самый популярный пост в С++ Правила аннулирования Iterator утверждают, что он не ясен, если итераторы прошедшего конца (т.е. те, которые возвращаются end(), cend(), rend() и crend()) недействительны в соответствии с теми же правилами, что и обычные итераторы, которые указывают на элементы в контейнере. Эти претензии, сделанные как для С++, так и для С++, откладывают до публикации обсуждения правил аннулирования конца итератора, где принятый ответ предполагает, что стандарт 2003 года неоднозначен по этому вопросу. Этот вывод основан на комментарии в 23.1/10 (в контексте swap()), который, по-видимому, подразумевает, что, когда спецификация явно не упоминает о недействительности итераторов прошлого, они могут быть признаны недействительными.

Комментарий к этому вопросу (майк-сеймур) предполагает, что С++ 11 однозначен в этом вопросе, в случае deque s. Мой вопрос касается всех контейнеров:

  • В С++ 11 существуют ли какие-либо операции с контейнерами, которые могут привести к аннулированию итератора прошедшего конца, и где это поведение неоднозначно в спецификации языка?

Говорят иначе,

  • Могу ли я доверять действительности прошедшего конца итератора после выполнения операции с контейнером, которая не говорит о том, что это может привести к аннулированию итераторов прошедшего конца?
4b9b3361

Ответ 1

Мой вопрос касается всех контейнеров:

  • В С++ 11 существуют ли какие-либо операции с контейнерами, которые могут привести к аннулированию итератора прошедшего конца, и где это поведение неоднозначно в языковая спецификация?

Я не уверен, что вы имеете в виду под "там, где это поведение неоднозначно в спецификации языка", но, безусловно, есть операции, которые делают недействительными прошлые операторы (например, вставлять в std::vector или std::string).

Говорят иначе,

  • Могу ли я доверять действительности прошедшего конца итератора после выполнения операции с контейнером, которая не говорит о том, что она может аннулировать итераторы прошедшего конца?

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

Ответ 2

Вы должны быть в состоянии доверять ему, если в стандарте указано, что операция не приведет к аннулированию итераторов. Все остальное должно рассматриваться как ошибка в стандартной реализации библиотеки.

Ответ 3

По крайней мере, в конце GCC итератор становится недействительным для std:: map:

#include <set>
#include <stdlib.h>
#include <assert.h>
int main() {
  std::set<int> a;
  a.insert(1);
  std::set<int>::reverse_iterator rit(a.rbegin());
  ++rit;
  assert(rit==a.rend());
  a.erase(a.begin());
  assert(a.rend()==rit); // FAIL
}