Последнее обновление:2026-10-12
Инвалидация итераторов STL¶
https://stackoverflow.com/questions/6438086/iterator-invalidation-rules-for-c-containers
Вставка Последовательные контейнеры
- vector: все итераторы и ссылки до точки вставки не затрагиваются, если только новый размер контейнера не превосходит прежнюю ёмкость (в этом случае инвалидируются все итераторы и ссылки) [23.3.6.5/1]
- deque: инвалидируются все итераторы и ссылки, кроме случая, когда вставка происходит на концах deque (спереди или сзади; в этом случае инвалидируются все итераторы, но ссылки на элементы не затрагиваются) [23.3.3.4/1]
- list: все итераторы и ссылки не затрагиваются [23.3.5.4/1]
- forward_list: все итераторы и ссылки не затрагиваются (применимо к insert_after) [23.3.4.5/1]
- array: (неприменимо)
Ассоциативные контейнеры
- [multi]{set,map}: все итераторы и ссылки не затрагиваются [23.2.4/9]
Неупорядоченные ассоциативные контейнеры
- unordered_[multi]{set,map}: при рехешировании инвалидируются все итераторы, но ссылки не затрагиваются [23.2.⅝]. Если вставка не приводит к превышению размером контейнера величины z * B, рехеширования не происходит, где z — максимальный коэффициент заполнения, B — текущее число корзин [23.2.5/14]
Адаптеры контейнеров
- stack: наследует поведение нижележащего контейнера
- queue: наследует поведение нижележащего контейнера
- priority_queue: наследует поведение нижележащего контейнера
Удаление Последовательные контейнеры
- vector: инвалидируется каждый итератор и ссылка начиная с точки удаления [23.3.6.5/3]
- deque: удаление последнего элемента инвалидирует лишь итераторы и ссылки на удаляемый элемент и past-the-end-итератор; удаление первого элемента инвалидирует лишь итераторы и ссылки на удаляемый элемент; удаление любого другого элемента инвалидирует все итераторы и ссылки (включая past-the-end-итератор) [23.3.3.4/4]
- list: инвалидируются лишь итераторы и ссылки на удаляемый элемент [23.3.5.4/3]
- forward_list: инвалидируются лишь итераторы и ссылки на удаляемый элемент (применимо к erase_after) [23.3.4.5/1]
- array: (неприменимо)
Ассоциативные контейнеры
- [multi]{set,map}: инвалидируются лишь итераторы и ссылки на удаляемый элемент [23.2.4/9]
Неупорядоченные ассоциативные контейнеры
- unordered_[multi]{set,map}: инвалидируются лишь итераторы и ссылки на удаляемый элемент [23.2.5/13]
Адаптеры контейнеров
- stack: наследует поведение нижележащего контейнера
- queue: наследует поведение нижележащего контейнера
- priority_queue: наследует поведение нижележащего контейнера
Изменение размера - vector: то же, что для вставки/удаления [23.3.6.5/12] - deque: то же, что для вставки/удаления [23.3.3.3/3] - list: то же, что для вставки/удаления [23.3.5.3/1] - forward_list: то же, что для вставки/удаления [23.3.4.5/25] - array: (неприменимо)
Примечание 1 Если иное явно не оговорено (будь то прямым указанием или через определение функции посредством другой функции), вызов функции-члена контейнера или передача контейнера в качестве аргумента библиотечной функции не должен инвалидировать итераторы на объекты в этом контейнере или изменять их значения. [23.2.1/11]
Примечание 2 Ни одна функция swap() не инвалидирует ссылки, указатели или итераторы на элементы обмениваемых контейнеров. [Примечание: итератор end() не указывает ни на какой элемент, поэтому он может инвалидироваться. — конец примечания] [23.2.1/10]
Примечание 3 За исключением приведённого выше предупреждения о swap(), неясно, подчиняются ли итераторы «end» каждому из указанных выше правил для контейнеров; в любом случае следует считать, что подчиняются.
Примечание 4 vector и все неупорядоченные ассоциативные контейнеры поддерживают reserve(n), гарантирующий, что автоматическое изменение размера не произойдёт, по крайней мере пока размер контейнера не вырастет до n. С неупорядоченными ассоциативными контейнерами следует быть осторожным: будущие предложения позволят задавать минимальный коэффициент заполнения, что даст возможность рехеширования при вставке после того, как достаточное число удалений уменьшит размер контейнера ниже минимума; поэтому после удалений эту гарантию следует считать потенциально недействительной.
https://en.cppreference.com/w/cpp/container#Iterator_invalidation
for (auto it = c.begin(); it != c.end(); /*inc in loop*/)
{
if (it->shouldErase())
{
it = c.erase(it);
continue;
}
...
++it;
}
auto is_dead = [](auto const& e) { return !(e->is_alive()); };
std::erase_if(m_entities, is_dead);
std::erase_if(m_entity_map, is_dead);
erase_if or remove_if
https://stackoverflow.com/questions/39019806/using-erase-remove-if-idiom
https://kera.name/articles/2011/06/iterator-invalidation-rules-c0x/
Похожие темы¶
- Анализ исходников STL array | C++那些事
- Глубокий анализ STL string | C++那些事
- Разбор вопросов собеседования про STL string | C++那些事
- Анализ исходников STL deque | C++那些事
- Оптимизация пустого базового класса EBO в STL | C++那些事
- Реализация хеш-таблицы своими руками | C++那些事
- Хеш-таблица STL hashtable | C++那些事
- Анализ исходников STL итераторов | C++那些事
- Анализ исходников STL list | C++那些事
- STL map и multimap | C++那些事