std::remove, std::remove_if - cppreference.com
</tbody> <tbody class="t-dcl-rev t-dcl-rev-num "> </tbody><tbody> </tbody> <tbody class="t-dcl-rev t-dcl-rev-num "> </tbody><tbody>
| Definido en el archivo de encabezado |
||
| (1) | ||
|
(constexpr desde C++20) (hasta C++26) |
|
|
|
(desde C++26) | |
| (2) | ||
|
|
(desde C++17) (hasta C++26) |
|
|
|
(desde C++26) | |
|
(3) | (constexpr desde C++20) |
|
|
(4) | (desde C++17) |
Elimina todos los elementos que satisfacen un criterio específico del rango [first, last) y devuelve un iterador pasado el final para el nuevo final del rango.
1) Elimina todos los elementos que son iguales a value (usando operator==).
3) Elimina todos los elementos para los que el predicado p devuelve true.
2,4) Igual que (1,3), pero se ejecuta de acuerdo a la política de ejecución policy.
Estas sobrecargas no participan en la resolución de sobrecarga a menos que std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> (hasta C++20) std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> (desde C++20) sea verdadera.
Explicación
La eliminación se realiza desplazando los elementos del rango de forma que los elementos que no se van a eliminar aparezcan al principio del rango.
- El desplazamiento se realiza mediante la asignación de copia (hasta C++11)asignación de movimiento (desde C++11).
- La operación de eliminación es estable: el orden relativo de los elementos que no se eliminarán permanece igual.
- La secuencia subyacente de
[first,last)no se acorta mediante la operación de eliminación. Dadoresultcomo el iterador devuelto:
- Todos los iteradores en
[result,last)siguen siendo desreferenciables.
- Todos los iteradores en
|
(desde C++11) |
Parámetros
| first, last | - | El rango de elementos a procesar. |
| value | - | El valor de los elementos a eliminar. |
| policy | - | La política de ejecución a usar. Véase política de ejecución para más detalles. |
| p | - | Predicado unario que devuelve true Si el elemento debe ser eliminado..
La expresión |
| Requisitos de tipo | ||
-ForwardIt debe satisfacer los requisitos de ForwardIterator.
| ||
-UnaryPredicate debe satisfacer los requisitos de Predicado.
| ||
Valor de retorno
Iterador pasado del final para el nuevo rango de valores (si éste no es end, entonces apunta a un valor no especificado, al igual que los iteradores a cualquier valor entre este iterador y end).
Complejidad
Dada N como std::distance(first, last):
1,2) Exactamente N comparaciones usando operator==.
3,4) Exactamente N aplicaciones del predicado p.
Excepciones
Las sobrecargas con un parámetro de plantilla llamado ExecutionPolicy (política de ejecución) reportan errores tales que:
- Si la ejecución de una función invocada como parte del algoritmo lanza una excepción y la política de ejecución es una de las tres políticas estándar, se llama a std::terminate. Para cualquier otra política de ejecución, el comportamiento está definido por la implementación.
- Si el algoritmo falla al asignar memoria, se lanza std::bad_alloc.
Posible implementación
| remove (1) |
|---|
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type> ForwardIt remove(ForwardIt first, ForwardIt last, const T& value) { first = std::find(first, last, value); if (first != last) for (ForwardIt i = first; ++i != last;) if (!(*i == value)) *first++ = std::move(*i); return first; } |
| remove_if (3) |
template<class ForwardIt, class UnaryPred> ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPred p) { first = std::find_if(first, last, p); if (first != last) for (ForwardIt i = first; ++i != last;) if (!p(*i)) *first++ = std::move(*i); return first; } |
Notas
Una llamada a remove suele ir seguida de una llamada a la función miembro erase de un contenedor para eliminar elementos del contenedor. Estas dos invocaciones juntas constituyen lo que se denomina el modismo borrar-eliminar.
|
El mismo efecto también se puede lograr con las siguientes funciones no miembro:
|
(desde C++20) |
Las funciones miembro de nombre similar, de los contenedores list::remove, list::remove_if, forward_list::remove y forward_list::remove_if borran los elementos eliminados.
Estos algoritmos no se pueden utilizar con contenedores asociativos como std::set y std::map porque sus tipos de iterador no hacen desreferencia a los tipos AsignablePorMovimiento (las claves en estos contenedores no son modificables).
La biblioteca estándar también define una sobrecarga de std::remove en <cstdio>, que toma un const char* y se utiliza para eliminar archivos.
Debido a que std::remove toma value por referencia, puede tener un comportamiento no esperado si es una referencia a un elemento del rango [first, last).
| Macro de Prueba de característica | Valor | Estándar | Comentario |
|---|---|---|---|
__cpp_lib_algorithm_default_value_type |
202403 |
(C++26) | inicialización por lista para los algoritmos (1,2) |
Ejemplo
El siguiente código elimina todos los espacios de una cadena desplazando todos los caracteres que no son espacios a la izquierda y luego borrando el extra. Esto es un ejemplo del modismo borrar-eliminar.
#include <algorithm> #include <cassert> #include <cctype> #include <complex> #include <iostream> #include <string> #include <string_view> #include <vector> int main() { std::string str1 {"Texto con algunos espacios"}; auto noSpaceEnd = std::remove(str1.begin(), str1.end(), ' '); // Los espacios se eliminan de la cadena solo lógicamente. // Usamos una vista sobre cadena, la cadena original aún no se ha reducido: std::cout << std::string_view(str1.begin(), noSpaceEnd) << " tamaño: " << str1.size() << '\n'; str1.erase(noSpaceEnd, str1.end()); // Los espacios se eliminan de la cadena físicamente. std::cout << str1 << " tamaño: " << str1.size() << '\n'; std::string str2 = "Texto\n con\talgunos \t espacios en blanco\n\n"; str2.erase(std::remove_if(str2.begin(), str2.end(), [](unsigned char x) { return std::isspace(x); }), str2.end()); std::cout << str2 << '\n'; std::vector<std::complex<double>> nums{{2, 2}, {1, 3}, {4, 8}}; #ifdef __cpp_lib_algorithm_default_value_type nums.erase(std::remove(nums.begin(), nums.end(), {1, 3}), nums.end()); #else nums.erase(std::remove(nums.begin(), nums.end(), std::complex<double>{1, 3}), nums.end()); #endif assert((nums == std::vector<std::complex<double>>{{2, 2}, {4, 8}})); }
Salida:
Textoconalgunosespacios tamaño: 28 Textoconalgunosespacios tamaño: 23 Textoconalgunosespaciosenblanco
Informes de defectos
Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.
| ID | Aplicado a | Comportamiento según lo publicado | Comportamiento correcto |
|---|---|---|---|
| LWG 283 | C++98 | Se requería que T fuera ComparableEnIgualdad, peroel tipo valor de ForwardIt no siempre es T.
|
Se requiere que el tipo valor de ForwardIten su lugar sea AsignablePorCopia. |