Lambdas: a first look
A function cannot be defined inside another function: the compiler rejects int twice(int x) { return x * 2; } inside main. Yet a short function is often needed in one place only, and moving it out of main is inconvenient. Such a function can be written right where it is needed, as a lambda:
#include <iostream>
int main() {
auto twice = [](int x) { return x * 2; };
std::cout << twice(21) << '\n'; // 42
}Anatomy of a lambda
A lambda is a function without a name, written right inside an expression. The square brackets [] start the lambda, the parentheses hold the parameters, and the braces hold the body. The compiler deduces the return type from return, the way an auto variable gets its type from its value. In the example, x * 2 has type int, so the lambda returns int too.
A lambda is stored in a variable declared with auto: the lambda has a type, but the code cannot name it. Every lambda gets its own type, made up by the compiler. The lambda is called through the variable's name, like an ordinary function: twice(21). A lambda takes parameters the way a function does: by value or by reference.
Capturing variables
For the lambda to use the local variable step from main, the variable must be captured. A capture is a variable the lambda takes from the surrounding code; captures are listed in the square brackets. [step] copies step when the lambda is created, while [&step] gives the lambda a reference to step itself:
#include <iostream>
int main() {
int step = 10;
auto add_copy = [step](int x) { return x + step; };
auto add_ref = [&step](int x) { return x + step; };
step = 100;
std::cout << add_copy(1) << ' ' << add_ref(1) << '\n'; // 11 101
}add_copy keeps a copy holding 10. It was made when the line with the lambda ran, so the change to step does not reach it. add_ref reads step itself, which is 100 by the time of the call.
Capturing by reference also lets a lambda change the variable: [&count]() { ++count; } increases count from main on every call. A copy from [step] can only be read: [step]() { ++step; } does not compile. Several variables are listed with commas: [a, &b].
Common mistake
A variable is used in a lambda but not captured:
int main() {
int step = 10;
auto add = [](int x) { return x + step; }; // ✗
return add(1);
}error: variable 'step' cannot be implicitly captured in a lambda with no capture-default specifiedThis is a compiler error: empty brackets [] mean the lambda captures nothing. Add the variable to the capture: [step] or [&step].