Última atualização:2026-10-12
Invalidação de iteradores na STL¶
https://stackoverflow.com/questions/6438086/iterator-invalidation-rules-for-c-containers
Inserção Contêineres sequenciais
- vector: todos os iteradores e referências anteriores ao ponto de inserção permanecem válidos, a menos que o novo tamanho do contêiner exceda a capacidade anterior (nesse caso, todos os iteradores e referências são invalidados) [23.3.6.5/1]
- deque: todos os iteradores e referências são invalidados, a menos que o elemento inserido esteja em uma das extremidades do deque (frente ou fundo) (nesse caso, todos os iteradores são invalidados, mas as referências aos elementos permanecem válidas) [23.3.3.4/1]
- list: nenhum iterador ou referência é invalidado [23.3.5.4/1]
- forward_list: nenhum iterador ou referência é invalidado (aplica-se a insert_after) [23.3.4.5/1]
- array: (não aplicável)
Contêineres associativos
- [multi]{set,map}: nenhum iterador ou referência é invalidado [23.2.4/9]
Contêineres associativos não ordenados
- unordered_[multi]{set,map}: quando ocorre um rehash, todos os iteradores são invalidados, mas as referências permanecem válidas [23.2.⅝]. Se a inserção não fizer com que o tamanho do contêiner exceda z * B, não ocorre rehash, onde z é o fator de carga máximo e B é o número atual de buckets [23.2.5/14]
Adaptadores de contêiner
- stack: herda do contêiner subjacente
- queue: herda do contêiner subjacente
- priority_queue: herda do contêiner subjacente
Remoção Contêineres sequenciais
- vector: todo iterador e referência a partir do ponto de remoção são invalidados [23.3.6.5/3]
- deque: remover o último elemento invalida apenas iteradores e referências ao elemento removido e o iterador past-the-end; remover o primeiro elemento invalida apenas iteradores e referências ao elemento removido; remover qualquer outro elemento invalida todos os iteradores e referências (incluindo o iterador past-the-end) [23.3.3.4/4]
- list: apenas iteradores e referências ao elemento removido são invalidados [23.3.5.4/3]
- forward_list: apenas iteradores e referências ao elemento removido são invalidados (aplica-se a erase_after) [23.3.4.5/1]
- array: (não aplicável)
Contêineres associativos
- [multi]{set,map}: apenas iteradores e referências ao elemento removido são invalidados [23.2.4/9]
Contêineres associativos não ordenados
- unordered_[multi]{set,map}: apenas iteradores e referências ao elemento removido são invalidados [23.2.5/13]
Adaptadores de contêiner
- stack: herda do contêiner subjacente
- queue: herda do contêiner subjacente
- priority_queue: herda do contêiner subjacente
Redimensionamento - vector: o mesmo que para inserção/remoção [23.3.6.5/12] - deque: o mesmo que para inserção/remoção [23.3.3.3/3] - list: o mesmo que para inserção/remoção [23.3.5.3/1] - forward_list: o mesmo que para inserção/remoção [23.3.4.5/25] - array: (não aplicável)
Nota 1 Salvo disposição em contrário explicitamente definida (seja explicitamente ou por meio de funções que definem outras funções), chamar uma função-membro de um contêiner ou passar um contêiner como argumento a uma função da biblioteca não deve invalidar iteradores para objetos nesse contêiner nem alterar seus valores. [23.2.1/11]
Nota 2 Nenhuma função swap() invalida referências, ponteiros ou iteradores que apontem para os elementos dos contêineres que estão sendo trocados. [Nota: o iterador end() não aponta para nenhum elemento, de modo que pode ser invalidado. — fim da nota] [23.2.1/10]
Nota 3 Com exceção da ressalva acima sobre swap(), não está claro se os iteradores "end" estão sujeitos a cada uma das regras de contêiner acima; em qualquer caso, você deve assumir que estão.
Nota 4 vector e todos os contêineres associativos não ordenados oferecem suporte a reserve(n), que garante que nenhum redimensionamento automático ocorra pelo menos até que o tamanho do contêiner cresça para n. Deve-se ter cautela com os contêineres associativos não ordenados, pois propostas futuras permitirão especificar um fator de carga mínimo, o que permitirá que um rehash ocorra na inserção depois que remoções suficientes reduzam o tamanho do contêiner abaixo desse mínimo; portanto, após remoções, essa garantia deve ser considerada possivelmente inválida.
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 ou remove_if
https://stackoverflow.com/questions/39019806/using-erase-remove-if-idiom
https://kera.name/articles/2011/06/iterator-invalidation-rules-c0x/
Tópicos relacionados¶
- Análise do código-fonte do STL array | C++那些事
- Análise aprofundada do STL string | C++那些事
- Questões de entrevista sobre STL string explicadas | C++那些事
- Análise do código-fonte do STL deque | C++那些事
- STL otimização de classe base vazia EBO | C++那些事
- STL implementação manual de tabela hash | C++那些事
- STL hashtable tabela hash | C++那些事
- Análise do código-fonte dos iteradores da STL | C++那些事
- Análise do código-fonte do STL list | C++那些事
- STL map e multimap | C++那些事