The erase–remove idiom is a common C++ technique to eliminate elements that fulfill a certain criterion from a C++ Standard Library container.[1][2][3]
Motivation
A common programming task is to remove all elements that have a certain value or fulfill a certain criterion from a collection. In C++, this can be achieved using a hand-written loop. It is, however, preferable to use an algorithm from the C++ Standard Library for such tasks.[1][2][3]
The member function erase
can be used to delete an element from a collection, but for containers which are based on an array, such as vector
, all elements after the deleted element have to be moved forward to avoid "gaps" in the collection. Calling erase multiple times on the same container generates much overhead from moving the elements.
The algorithm
library provides the remove
and remove_if
algorithms for this. Because these algorithms operate on a range of elements denoted by two forward iterators, they have no knowledge of the underlying container or collection.[1][4]
These algorithms do not remove elements from the container, but move all elements that do not fit the removal criteria to the front of the range, keeping the relative order of the elements. This is done in a single pass through the data range.
As no elements are actually removed and the container retains the same size, the tail of the array has a length equal to the number of "removed" items; these items remain in memory but in an unspecified state. remove
returns an iterator pointing to the first of these tail elements so that they can be deleted using a single call to erase
.
Doing the same using only erase
results in as many passes as there are elements to remove. For each of these passes, all elements after the erased element have to be moved, which is more time-consuming than shifting elements in a single pass.
C++20
As of C++20, the free functions std::erase
and std::erase_if
are provided for STL containers. These convenience functions can be used to perform correct erasure of elements without requiring the programmer to explicitly use the erase-remove idiom.[5]
Limitation
The erase–remove idiom cannot be used for containers that return const_iterator
(e.g.: set)[6]
std::remove
and/or std::remove_if
do not maintain elements that are removed (unlike std::partition
, std::stable_partition
). Thus, erase–remove can only be used with containers holding elements with full value semantics without incurring resource leaks.[7]
Example
// Use g++ -std=c++11 or clang++ -std=c++11 to compile.
#include <algorithm> // remove and remove_if
#include <iostream>
#include <vector>
void Print(const std::vector<int>& vec) {
for (auto val : vec) {
std::cout << val << ' ';
}
std::cout << '\n';
}
int main() {
std::vector<int> v = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
Print(v);
// Removes all elements with the value 5.
v.erase(std::remove(v.begin(), v.end(), 5), v.end());
Print(v);
// Removes all odd numbers.
v.erase(std::remove_if(v.begin(), v.end(), [](int val) { return val & 1; }),
v.end());
Print(v);
}
/*
Output:
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 6 7 8 9
0 2 4 6 8
*/
References
Wikiwand in your browser!
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.