HOWTO · C++
Cómo quitar el elemento del vector en C++
Este artículo demuestra cómo eliminar un elemento del vector en C++
En esta página
Para eliminar una posición o un rango conocidos, llama a std::vector::erase. Para eliminar todos los elementos iguales a un valor en C++20, usa std::erase; con estándares anteriores de C++, combina std::remove y erase mediante el modismo erase-remove. Los ejemplos muestran cómo cambia el vector con cada opción y cómo mantener válidos los iteradores.
Eliminar un elemento con std::vector::erase
std::vector::erase acepta un iterador a un elemento o un rango semiabierto [first, last). El rango incluye first y excluye last. La sobrecarga para un solo elemento requiere un iterador válido que apunte a un elemento. Devuelve un iterador al elemento que sigue al rango eliminado o end() si no hay ningún elemento después.
Este ejemplo completo elimina el elemento en el índice 2 y luego lee el iterador devuelto:
Ejecuta este ejemplo:
El código y las etiquetas o salidas visibles de esta sección se mantienen en 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
Al borrar, se invalidan los iteradores y las referencias situados en la posición eliminada o después de ella. Actualiza esos identificadores o deja de usarlos antes de volver a utilizarlos. Para borrar un rango, pasa su primer iterador y el iterador que apunta justo después del último elemento; el iterador devuelto y las reglas de invalidación son los mismos. Si el rango eliminado llega hasta el final, el iterador devuelto es igual a numbers.end() y no se puede desreferenciar.
Eliminar todos los valores coincidentes con std::erase (C++20)
C++20 incorpora la sobrecarga no miembro std::erase para std::vector, declarada a través de <vector>. Elimina todos los elementos iguales al valor indicado y devuelve la cantidad eliminada. Si hay coincidencias repetidas, las elimina todas; por eso resulta útil cuando la selección se basa en la igualdad. Los estándares anteriores del lenguaje no incluyen esta sobrecarga; usa el modismo erase-remove de la siguiente sección.
Este ejemplo usa std::erase al compilarse como C++20 y, con un estándar anterior, recurre a erase-remove. Ambas ramas eliminan todas las apariciones de 2 y muestran la cantidad eliminada:
El código y las etiquetas o salidas visibles de esta sección se mantienen en 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
La sobrecarga de std::erase para std::vector está disponible desde C++20 y devuelve la cantidad de elementos eliminados. La rama para estándares anteriores usa el modismo erase-remove, que se explica a continuación.
Eliminar valores coincidentes con el modismo erase-remove
Antes de C++20, combina std::remove de <algorithm> con el método miembro erase del vector. std::remove desplaza los valores que no coinciden hacia el principio del rango modificable y devuelve un iterador a su nuevo final lógico. No cambia el tamaño del vector: este sigue teniendo la cantidad original de elementos hasta que se borra el rango final. Pasa a erase el iterador devuelto y el end() original del vector para reducir el tamaño del contenedor.
Este ejemplo elimina todas las apariciones de 2 con ese patrón de dos pasos:
El código y las etiquetas o salidas visibles de esta sección se mantienen en 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';
}
El rango que se pasa a std::remove debe ser modificable, porque el algoritmo reorganiza los valores que se conservan. Que un contenedor permita acceso de solo lectura mediante iteradores constantes no impide usar este modismo si se dispone de un rango de iteradores modificables.
Borrar elementos de forma segura durante la iteración
Cuando un predicado u otra condición determina qué elementos eliminar, usa un bucle con iterador. Después de borrar, asigna al iterador el valor devuelto por erase; increméntalo solo cuando se conserve el elemento actual. El iterador del elemento borrado queda invalidado, así que incrementarlo o desreferenciarlo es inseguro.
Este ejemplo elimina los valores pares y mantiene válido el iterador:
El código y las etiquetas o salidas visibles de esta sección se mantienen en 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';
}
Usa std::erase para eliminar valores iguales en C++20, el modismo erase-remove para esa tarea en estándares anteriores y erase con un bucle que usa el iterador devuelto cuando la eliminación depende de una condición. La opción adecuada depende de si la selección se basa en una posición o un rango conocidos, en la igualdad con un valor o en un predicado que se evalúa durante el bucle.