HOWTO · C++
How to Remove Element From Vector in C++
This article demonstrates how to remove an element from a vector in C++. Learn various methods such as using erase(), remove(), and custom loops to manage your vector data effectively. Enhance your C++ programming skills with clear examples and explanations.
On this page
To remove a known position or range, call std::vector::erase. For every element equal to a value in C++20, use std::erase; with earlier C++ standards, combine std::remove and erase in the erase-remove idiom. The examples show how each choice changes the vector and how to keep iterators valid.
Remove one element with std::vector::erase
std::vector::erase accepts an iterator to one element or a half-open range [first, last). The range includes first and excludes last. The single-element overload requires a valid iterator that points to an element. It returns an iterator to the element following the erased range, or end() if no element follows.
This complete example removes the element at index 2 and then reads the returned iterator:
Run this example:
#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
Erasing invalidates iterators and references at or after the erased position. Update or discard those handles before using them again. To erase a range, pass its first iterator and one-past-last iterator; the returned iterator and invalidation rules are the same. If the erased range reaches the end, the returned iterator equals numbers.end() and cannot be dereferenced.
Remove every matching value with std::erase (C++20)
C++20 adds the non-member std::erase overload for std::vector, declared through <vector>. It removes every element equal to the supplied value and returns the number removed. Repeated matches are all removed, so this is useful when selection is based on equality. Earlier language standards do not provide this overload; use the erase-remove idiom in the next section.
This example uses std::erase when compiled as C++20 and falls back to erase-remove with an earlier standard. Both branches remove every occurrence of 2 and print the number removed:
#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
The std::erase overload for std::vector is available from C++20 and returns the count removed. The earlier-standard branch uses the erase-remove idiom, which is explained below.
Remove matching values with the erase-remove idiom
Before C++20, combine std::remove from <algorithm> with the vector member erase. std::remove moves nonmatching values toward the beginning of the writable range and returns an iterator to their new logical end. It does not change the vector’s size: the vector still contains its original number of elements until the trailing range is erased. Pass the returned iterator and the vector’s original end() to erase to shrink the container.
This example removes every occurrence of 2 using that two-step pattern:
#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';
}
The range passed to std::remove must be writable because the algorithm rearranges retained values. A container’s read-only access through const iterators does not prevent use of the idiom when a writable iterator range is available.
Erase elements safely while iterating
When a predicate or another condition decides what to remove, use an iterator loop. After removal, assign the iterator returned by erase; increment it only when the current element stays. The erased iterator is invalid, so incrementing or dereferencing that old iterator is unsafe.
This example removes even values while keeping the iterator valid:
#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 for equality-based removal in C++20, the erase-remove idiom for that task in earlier standards, and erase with a returned-iterator loop when removal depends on a condition. The right choice follows from whether the selection is a known position or range, equality with a value, or a predicate evaluated as the loop proceeds.