Lesson content
Read, practise, then check your understanding
A lambda creates an unnamed closure object with a call operator. Its syntax contains a capture list, parameters, optional specifiers and return type, then a body.
#include <algorithm>
#include <vector>
std::vector<int> values{1, 7, 3, 9};
int threshold{5};
auto count = std::count_if(values.begin(), values.end(),
[threshold](int value) { return value > threshold; });
[x] captures by value, [&x] by reference, [=] used locals by value, and [&] by reference. Prefer explicit captures because lifetime and mutation remain visible. A returned or asynchronous lambda that captured a local by reference can dangle.
Generic and stateful lambdas
auto add = [](auto left, auto right) { return left + right; };
auto pointer = std::make_unique<int>(3);
auto task = [owned = std::move(pointer)]() mutable { return ++*owned; };
auto parameters make a generic lambda. Init-capture constructs closure members and can move ownership. Value captures are read-only inside the default const call operator; mutable permits changing the closure’s copies, not the original variables.
Capture this carefully because it is a pointer whose object may die; C++17’s [*this] captures a copy of the object. Captureless lambdas can convert to compatible function pointers. Use lambdas for short predicates, transformations, callbacks, and scope-local policy; name a regular function or class when behavior needs reuse, documentation, or complex state.
Knowledge check
Answer every question correctly to complete this chapter.
0 of 10 checks passed
Your progress is saved on this device.