C++ lambdas and the standard algorithms
Sort, search, count, transform, and remove elements with algorithms and small anonymous functions.
On this page
C++ vectors and iterators.
- Sort, search, count, transform, and remove elements with algorithms and small anonymous functions.
- Predict the sample output and explain the state changes.
- Complete the practice task and check the boundary cases.
The concept
The <algorithm> header provides functions that work on ranges given by two iterators: sort, find_if, count_if, transform, accumulate, and more. Many take a predicate or comparison function. A lambda expression writes such a function in place: [capture](parameters) { body }. The capture list copies or references variables from the surrounding scope.
The erase–remove idiom deletes elements that satisfy a condition. std::remove_if does not shrink the vector. It moves the elements to keep to the front and returns an iterator to the new end. The vector's erase member then discards the leftover tail. In C++20, std::erase_if does both steps at once.
Code example
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
void show(const char* label, const std::vector<int>& v) {
std::cout << label << ":";
for (int x : v) {
std::cout << " " << x;
}
std::cout << "\n";
}
int main() {
std::vector<int> v = {5, 2, 8, 1, 9, 3};
std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
show("descending", v);
auto it = std::find_if(v.begin(), v.end(), [](int x) { return x < 4; });
std::cout << "first below 4: " << *it << "\n";
int threshold = 4;
auto above = std::count_if(v.begin(), v.end(), [threshold](int x) { return x > threshold; });
std::cout << "above " << threshold << ": " << above << "\n";
std::vector<int> squares(v.size());
std::transform(v.begin(), v.end(), squares.begin(), [](int x) { return x * x; });
std::cout << "sum of squares: " << std::accumulate(squares.begin(), squares.end(), 0) << "\n";
v.erase(std::remove_if(v.begin(), v.end(), [](int x) { return x % 2 != 0; }), v.end());
show("evens only", v);
}descending: 9 8 5 3 2 1 first below 4: 3 above 4: 3 sum of squares: 184 evens only: 8 2
Follow the code
Open the walkthrough to inspect the example one step at a time.
Show guided walkthrough
#include <algorithm>#include <iostream>#include <numeric>#include <vector> void show(const char* label, const std::vector<int>& v) { std::cout << label << ":"; for (int x : v) { std::cout << " " << x; } std::cout << "\n";} int main() { std::vector<int> v = {5, 2, 8, 1, 9, 3}; std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; }); show("descending", v); auto it = std::find_if(v.begin(), v.end(), [](int x) { return x < 4; }); std::cout << "first below 4: " << *it << "\n"; int threshold = 4; auto above = std::count_if(v.begin(), v.end(), [threshold](int x) { return x > threshold; }); std::cout << "above " << threshold << ": " << above << "\n"; std::vector<int> squares(v.size()); std::transform(v.begin(), v.end(), squares.begin(), [](int x) { return x * x; }); std::cout << "sum of squares: " << std::accumulate(squares.begin(), squares.end(), 0) << "\n"; v.erase(std::remove_if(v.begin(), v.end(), [](int x) { return x % 2 != 0; }), v.end()); show("evens only", v);}Follow the example
Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.
View the complete dry-run table
| Step / line | What happens | State after step | Output so far |
|---|---|---|---|
| The lambda says a comes before b if a is larger, giving descending order. | — | — | |
| The sorted vector. | — | descending: 9 8 5 3 2 1 | |
| The first element below 4 in the new order is 3. | — | descending: 9 8 5 3 2 1 | |
| Dereference the iterator to read it. | — | descending: 9 8 5 3 2 1 first below 4: 3 | |
| The lambda captures threshold by value. 9, 8, and 5 are above 4. | — | descending: 9 8 5 3 2 1 first below 4: 3 | |
| Three elements. | — | descending: 9 8 5 3 2 1 first below 4: 3 above 4: 3 | |
| 81 + 64 + 25 + 9 + 4 + 1. | — | descending: 9 8 5 3 2 1 first below 4: 3 above 4: 3 sum of squares: 184 | |
| Remove the odd elements: remove_if shuffles the survivors forward, and erase drops the tail. | — | descending: 9 8 5 3 2 1 first below 4: 3 above 4: 3 sum of squares: 184 | |
| Only 8 and 2 remain, in their existing order. | — | descending: 9 8 5 3 2 1 first below 4: 3 above 4: 3 sum of squares: 184 evens only: 8 2 |
Behind the scenes
How C++ processes this code
The C++ compiler produces a native executable. Execution enters main, where objects and function calls perform the work.
Cost and common mistakes
sort is O(n log n); the other algorithms here are O(n).
- Dereferencing the result of find_if without checking it against end() is undefined behaviour when nothing matched.
- Calling remove_if without erase leaves the vector at its old size with unspecified values at the end.
- A lambda that captures by reference must not outlive the variables it refers to.
Try it yourself
How would you sort strings by length?
Reveal answer and reasoning
std::sort(words.begin(), words.end(), [](const std::string& a, const std::string& b) { return a.size() < b.size(); });