Перейти к содержанию

Последнее обновление: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/

Похожие темы

Комментарии