HOWTO · C++
Eliminar un elemento de un array en C++
Este artículo muestra cómo eliminar un elemento de un array en C++
En esta página
La forma de eliminar un valor depende del contenedor. Un array de estilo C conserva su capacidad declarada, así que el código puede desplazar valores y llevar la cuenta de una longitud lógica menor, o copiar los valores que se conservan a otro contenedor. Un std::vector puede cambiar de tamaño directamente. Los ejemplos siguientes eliminan una coincidencia o todas, según se indica.
Por qué eliminar un elemento cambia el tamaño lógico de un array
Un array como int values[5] siempre tiene espacio para cinco enteros. Sobrescribir un elemento con los valores posteriores puede acortar la secuencia activa, pero no cambia la capacidad del array. Guarda la longitud activa en una variable aparte y úsala al leer o imprimir la secuencia. En cambio, un std::vector<int> gestiona tanto su espacio de almacenamiento como el número actual de elementos.
Desplazar elementos en un array de estilo C
Para eliminar la primera aparición en el mismo array, búscala, desplaza una posición a la izquierda cada valor posterior y, después, reduce la longitud lógica. La capacidad del array sigue siendo cinco; solo los primeros length valores forman parte de la secuencia acortada. Ejecuta este ejemplo:
El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.
#include <iostream>
void remove_first(int values[], int& length, int target) {
int index = 0;
while (index < length && values[index] != target) {
++index;
}
if (index == length) {
return;
}
for (int i = index; i + 1 < length; ++i) {
values[i] = values[i + 1];
}
--length;
}
int main() {
int values[5] = {1, 2, 3, 4, 5};
int length = 5;
remove_first(values, length, 3);
for (int i = 0; i < length; ++i) {
if (i != 0) std::cout << ' ';
std::cout << values[i];
}
std::cout << '\n';
}
1 2 4 5
Esta función elimina solo la primera coincidencia. Para eliminar todas las apariciones, compacta el array con un índice de lectura y otro de escritura: copia cada valor distinto del buscado en la siguiente posición de escritura y, al final, establece la longitud lógica en el número de valores escritos. Así se recorre cada elemento una sola vez. Desplazar los elementos después de cada coincidencia es más sencillo, pero puede mover los mismos valores varias veces.
Copiar los elementos restantes en un array nuevo
Un destino independiente deja intacto el array de origen. Un std::vector es un destino práctico cuyo tamaño puede ajustarse y que gestiona su propio almacenamiento, sin necesidad de usar manualmente new[] y delete[]. Este ejemplo copia todos los valores distintos de 3; si no hay coincidencias, el destino simplemente contiene una copia del array de origen.
El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.
#include <cstddef>
#include <iostream>
#include <vector>
int main() {
const int source[] = {1, 2, 3, 3, 4, 5};
const int length = sizeof(source) / sizeof(source[0]);
std::vector<int> remaining;
for (int i = 0; i < length; ++i) {
if (source[i] != 3) {
remaining.push_back(source[i]);
}
}
for (std::size_t i = 0; i < remaining.size(); ++i) {
if (i != 0) std::cout << ' ';
std::cout << remaining[i];
}
std::cout << '\n';
}
1 2 4 5
El destino crece hasta contener exactamente los valores que se conservan. Si una interfaz exige un array asignado dinámicamente sin un contenedor, primero cuenta esos valores, asigna espacio para esa cantidad de elementos (que puede ser cero) y libera la asignación con delete[] cuando su propietario haya terminado de usarla. Si la interfaz no exige gestionar directamente la memoria, es preferible usar un contenedor estándar.
Eliminar valores coincidentes de std::vector con el modismo erase-remove
Para un contenedor redimensionable, usa std::remove junto con el miembro erase del vector. Incluye <algorithm> para el algoritmo y <vector> para el contenedor. std::remove desplaza los valores que no coinciden hacia el principio y devuelve un iterador a la nueva posición final lógica; no cambia el tamaño del vector. A continuación, erase elimina el rango restante y actualiza el tamaño. Así se eliminan todas las apariciones del valor buscado.
El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.
#include <algorithm>
#include <cstddef>
#include <iostream>
#include <vector>
int main() {
std::vector<int> values = {1, 2, 3, 3, 4, 5};
values.erase(std::remove(values.begin(), values.end(), 3), values.end());
for (std::size_t i = 0; i < values.size(); ++i) {
if (i != 0) std::cout << ' ';
std::cout << values[i];
}
std::cout << '\n';
}
1 2 4 5
Usar std::remove con un array de tamaño fijo
std::remove también funciona con el rango de iteradores de un array de estilo C. Reordena los valores y devuelve la nueva posición final lógica, pero no puede reducir el espacio de almacenamiento del array. Cada vez que proceses el resultado, usa el iterador devuelto como final del rango conservado; no trates el rango completo original del array como si fuera la secuencia acortada.
El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.
#include <algorithm>
#include <iostream>
#include <iterator>
int main() {
int values[] = {1, 2, 2, 3, 4};
int* logical_end = std::remove(std::begin(values), std::end(values), 2);
for (int* current = std::begin(values); current != logical_end; ++current) {
if (current != std::begin(values)) std::cout << ' ';
std::cout << *current;
}
std::cout << '\n';
}
1 3 4
Los elementos desde logical_end hasta el final real del array siguen siendo objetos válidos, pero el algoritmo no especifica sus valores. No los imprimas ni dependas de ellos. Si necesitas una secuencia físicamente más corta, copia el prefijo que termina en logical_end a un destino del tamaño adecuado.
Elegir un método y tratar los casos límite
Usa el desplazamiento cuando tengas que modificar un array de tamaño fijo en el mismo lugar y puedas llevar por separado la cuenta de su longitud lógica. Usa un destino nuevo si necesitas conservar intacto el original o almacenar el resultado de forma independiente. Elige std::vector cuando la colección deba poder crecer o reducirse de forma natural; su modismo erase-remove suele ser la forma más clara de eliminar todos los valores coincidentes.
Indica claramente si la operación elimina la primera coincidencia o todas. Si no hay coincidencias, la secuencia no cambia. Al eliminar el único elemento de un array, su longitud lógica puede pasar a cero, aunque su capacidad declarada siga siendo uno. Si el vector está vacío, std::remove devuelve begin() y borrar el rango vacío resultante lo deja vacío. Estos casos no requieren trucos especiales de asignación de memoria si se gestionan de manera coherente las longitudes y los rangos de iteradores.