HOWTO · C++
Remover Elemento de Vector em C++
Este artigo demonstra como remover um elemento do vector em C++
Nesta página
Para remover uma posição ou um intervalo conhecido, use std::vector::erase. Para remover todos os elementos iguais a um valor em C++20, use std::erase; em versões anteriores do C++, combine std::remove e erase com o idioma erase-remove. Os exemplos mostram como cada opção altera o vetor e como manter os iteradores válidos.
Remover um elemento com std::vector::erase
std::vector::erase aceita um iterador para um elemento ou um intervalo semiaberto [first, last). O intervalo inclui first e exclui last. A sobrecarga para um único elemento exige um iterador válido que aponte para um elemento. Retorna um iterador para o elemento seguinte ao intervalo removido ou end() se não houver elemento seguinte.
Este exemplo completo remove o elemento no índice 2 e, em seguida, lê o iterador devolvido:
Execute este exemplo:
O código e os rótulos ou saídas exibidos nesta seção permanecem em inglês.
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers{10, 20, 30, 40, 50};
auto next = numbers.erase(numbers.begin() + 2);
for (std::size_t i = 0; i < numbers.size(); ++i) {
if (i != 0) std::cout << ' ';
std::cout << numbers[i];
}
std::cout << "\nNext value: " << *next << '\n';
}
10 20 40 50
Next value: 40
A remoção invalida os iteradores e as referências na posição removida e depois dela. Atualize ou descarte esses identificadores antes de os voltar a usar. Para remover um intervalo, passe o iterador para o primeiro elemento e o iterador para a posição imediatamente após o último; o iterador devolvido e as regras de invalidação são os mesmos. Se o intervalo removido chegar ao fim, o iterador devolvido será igual a numbers.end() e não poderá ser desreferenciado.
Remover todos os valores correspondentes com std::erase (C++20)
O C++20 acrescenta a sobrecarga não membro std::erase para std::vector, declarada através de <vector>. Remove todos os elementos iguais ao valor fornecido e devolve a quantidade removida. Se houver correspondências repetidas, remove-as todas; por isso, é útil quando a seleção se baseia na igualdade. As versões anteriores da linguagem não disponibilizam esta sobrecarga; nesse caso, use o idioma erase-remove apresentado na secção seguinte.
Este exemplo usa std::erase quando é compilado como C++20 e recorre ao idioma erase-remove com uma versão anterior. Ambos os ramos removem todas as ocorrências de 2 e apresentam a quantidade removida:
O código e os rótulos ou saídas exibidos nesta seção permanecem em inglês.
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers{1, 2, 3, 2, 4, 2, 5};
std::size_t removed;
#if __cplusplus >= 202002L
removed = std::erase(numbers, 2);
#else
const auto old_size = numbers.size();
const auto new_end = std::remove(numbers.begin(), numbers.end(), 2);
numbers.erase(new_end, numbers.end());
removed = old_size - numbers.size();
#endif
std::cout << "Removed: " << removed << "\nRemaining: ";
for (std::size_t i = 0; i < numbers.size(); ++i) {
if (i != 0) std::cout << ' ';
std::cout << numbers[i];
}
std::cout << '\n';
}
Removed: 3
Remaining: 1 3 4 5
A sobrecarga de std::erase para std::vector está disponível a partir do C++20 e devolve a quantidade removida. O ramo para versões anteriores usa o idioma erase-remove, explicado abaixo.
Remover valores correspondentes com o idioma erase-remove
Antes do C++20, combine std::remove de <algorithm> com a função membro erase do vetor. std::remove desloca os valores que não correspondem para o início do intervalo modificável e devolve um iterador para o novo fim lógico. Não altera o tamanho do vetor: este continua a conter o número original de elementos até que o intervalo final seja removido. Passe o iterador devolvido e o end() original do vetor a erase para reduzir o contentor.
Este exemplo remove todas as ocorrências de 2 com esse padrão de duas etapas:
O código e os rótulos ou saídas exibidos nesta seção permanecem em inglês.
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers{1, 2, 3, 2, 4, 5};
const auto new_end = std::remove(numbers.begin(), numbers.end(), 2);
numbers.erase(new_end, numbers.end());
for (std::size_t i = 0; i < numbers.size(); ++i) {
if (i != 0) std::cout << ' ';
std::cout << numbers[i];
}
std::cout << '\n';
}
O intervalo passado a std::remove tem de ser modificável, porque o algoritmo reorganiza os valores que são mantidos. O acesso de leitura a um contentor através de iteradores constantes não impede o uso deste idioma quando está disponível um intervalo de iteradores modificáveis.
Remover elementos com segurança durante a iteração
Quando um predicado ou outra condição determina o que deve ser removido, use um ciclo com iterador. Depois de remover um elemento, atribua ao iterador o valor devolvido por erase; incremente-o apenas quando o elemento atual for mantido. O iterador do elemento removido fica inválido, por isso é inseguro incrementá-lo ou desreferenciá-lo.
Este exemplo remove os valores pares e mantém o iterador válido:
O código e os rótulos ou saídas exibidos nesta seção permanecem em inglês.
#include <iostream>
#include <vector>
int main() {
std::vector<int> numbers{1, 2, 3, 4, 5, 6, 7};
for (auto it = numbers.begin(); it != numbers.end();) {
if (*it % 2 == 0) {
it = numbers.erase(it);
} else {
++it;
}
}
for (std::size_t i = 0; i < numbers.size(); ++i) {
if (i != 0) std::cout << ' ';
std::cout << numbers[i];
}
std::cout << '\n';
}
Use std::erase para remover por igualdade em C++20, o idioma erase-remove para essa tarefa em versões anteriores e erase com um ciclo que usa o iterador devolvido quando a remoção depende de uma condição. A escolha adequada depende de a seleção ser uma posição ou um intervalo conhecido, a igualdade com um valor ou um predicado avaliado à medida que o ciclo avança.