Контейнеры не становятся недействительными - итераторы , ссылающиеся на элементы в контейнерах, становятся недействительными.
Итератор - это дескриптор определенного элемента в контейнере.Итератор действителен до тех пор, пока этот элемент остается внутри контейнера, и контейнер не перестраивается внутри себя.Итератор становится недействительным, когда происходит одна из этих двух вещей, поскольку после слов итератор больше не является допустимым в качестве дескриптора в контейнере.
Наиболее очевидный способ сделать недействительным итератор - удалить его элемент изколлекция, например:
std::set<int> s;
s.insert(4);
s.insert(2);
std::set<int>::iterator itr = s.find(4); // itr is a handle to 4
std::cout << *itr << std::endl; // prints 4
s.erase(4); // removes 4 from collection, invalidates itr
std::cout << *itr << std::endl; // undefined behavior
Более тонкий способ аннулировать итератор - заставить контейнер внутренне переставить себя (например, перераспределить внутреннее хранилище).Это может быть сделано, например, путем расширения определенных типов контейнеров:
std::vector<int> v;
v.push_back(4);
v.push_back(2);
std::vector<int>::iterator itr = v.begin(); // itr is a handle to 4
std::cout << *itr << std::endl; // prints 4
v.push_back(12); // MIGHT invalidate itr, if v expands its internal allocation
В некоторых контейнерах это можно предотвратить, предварительно зарезервировав пространство:
std::vector<int> v;
v.reserve(3); // Pre-allocate 3 elements
v.push_back(4);
v.push_back(2);
std::vector<int>::iterator itr = v.begin(); // itr is a handle to 4
std::cout << *itr << std::endl; // prints 4
v.push_back(12); // WILL NOT invalidate itr, since it will never cause v to expand
Документациядля каждого контейнера STL следует описать, при каких обстоятельствах аннулирование итератора произойдет или может произойти.