C++ · Course navigation

C++ lambdas and the standard algorithms

Sort, search, count, transform, and remove elements with algorithms and small anonymous functions.

On this page
Before you start

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

C++
#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);
}
Output
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
Guided walkthroughReady
1#include <algorithm>
2#include <iostream>
3#include <numeric>
4#include <vector>
5
6void show(const char* label, const std::vector<int>& v) {
7 std::cout << label << ":";
8 for (int x : v) {
9 std::cout << " " << x;
10 }
11 std::cout << "\n";
12}
13
14int main() {
15 std::vector<int> v = {5, 2, 8, 1, 9, 3};
16
17 std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; });
18 show("descending", v);
19
20 auto it = std::find_if(v.begin(), v.end(), [](int x) { return x < 4; });
21 std::cout << "first below 4: " << *it << "\n";
22
23 int threshold = 4;
24 auto above = std::count_if(v.begin(), v.end(), [threshold](int x) { return x > threshold; });
25 std::cout << "above " << threshold << ": " << above << "\n";
26
27 std::vector<int> squares(v.size());
28 std::transform(v.begin(), v.end(), squares.begin(), [](int x) { return x * x; });
29 std::cout << "sum of squares: " << std::accumulate(squares.begin(), squares.end(), 0) << "\n";
30
31 v.erase(std::remove_if(v.begin(), v.end(), [](int x) { return x % 2 != 0; }), v.end());
32 show("evens only", v);
33}

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
Prepared trace of the published program. Some rows group repeated iterations.
Step / lineWhat happensState after stepOutput 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(); });

Further reading