コンテンツにスキップ

最終更新: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 または remove_if

https://stackoverflow.com/questions/39019806/using-erase-remove-if-idiom

https://kera.name/articles/2011/06/iterator-invalidation-rules-c0x/

関連トピック

コメント