auto add = [](int a, int b) { return a + b; };
int r = add(2, 3); // 5
C++
Topics in this category
Casting & Conversions
Compilation & Linking
Concepts & Constraints
Concurrency
Const Correctness
Constexpr & Compile-Time
Coroutines
Enums & Enum Classes
Exception Handling
I/O Streams
Lambda Expressions
Memory Management
Modern C++
Move Semantics
Namespaces
OOP & Classes
Operator Overloading
Preprocessor & Macros
RAII & Smart Pointers
Ranges & Views
C++
Lambda Expressions
A lambda expression is an anonymous function object defined inline, introduced in C++11. It has the form [captures](params){ body } and can be stored, passed to algorithms, or called immediately. The compiler generates a unique closure type with an operator() containing the body.
Real-world example
A lambda is passed to std::sort to define a custom comparison inline instead of a named function.
STL
Templates
Lambda Expressions
The capture list [...] specifies which surrounding variables the lambda can use and how. [x] captures x by value (a copy), [&x] by reference, [=] captures all used variables by value, [&] all by reference, and [this] captures the enclosing object. Captures let the lambda access local state.
int n = 10;
auto byVal = [n]() { return n; }; // copy
auto byRef = [&n]() { n++; }; // reference
Real-world example
A lambda captures a threshold value by value so it can filter a collection with std::count_if.
Lambda Expressions
STL
Lambda Expressions
Capturing by value copies the variable into the closure at creation time, so later changes to the original don't affect the lambda and the copy is safe to use after the original's scope ends. Capturing by reference stores a reference, so the lambda sees later changes but causes dangling references if it outlives the captured variable.
int x = 1;
auto v = [x] { return x; }; // frozen at 1
auto r = [&x] { return x; }; // reflects later x
x = 99;
Real-world example
Capturing a local by reference in a lambda stored for later use causes a dangling-reference crash.
References & Pointers
Lambda Expressions
Lambda Expressions
By default, a lambda's operator() is const, so by-value captured variables can't be modified inside the body. Marking the lambda mutable removes the const, allowing modification of the by-value copies (the changes persist across calls to that lambda instance but don't affect the originals).
int n = 0;
auto counter = [n]() mutable { return ++n; };
counter(); counter(); // returns 1, then 2
Real-world example
A mutable lambda maintains an internal counter across calls without an external variable.
Lambda Expressions
Lambda Expressions
Lambda Expressions
Usually the return type is deduced from the return statements. When deduction is ambiguous or you want an explicit type, use a trailing return type: [](int x) -> double { ... }. Explicit return types are also needed when different return statements would otherwise deduce different types.
auto f = [](int x) -> double {
if (x > 0) return x; // int
return 0.5; // double -> need explicit type
};
Real-world example
An explicit -> double return type resolves a lambda that returns both int and double literals.
Type Deduction & auto
Lambda Expressions
Lambda Expressions
A generic lambda (C++14) uses auto for one or more parameters, making operator() a template so the lambda works with any argument types. C++20 adds explicit template parameter syntax. Generic lambdas enable writing reusable, type-agnostic inline functions, often used with algorithms over varied types.
auto print = [](const auto& x) { std::cout << x; };
print(42); print("hi"); // works for both
// C++20 explicit form
auto f = []<typename T>(T x) { return x + x; };
Real-world example
A single generic lambda logs elements of containers holding different value types.
Templates
Type Deduction & auto
Lambda Expressions
The compiler turns a lambda into an unnamed class (closure type) with a member operator() holding the body, and member variables for the captures (copies for by-value, references for by-reference). A captureless lambda is convertible to a plain function pointer. Because each lambda has a unique type, they're typically stored via auto or std::function.
// [x](int y){return x+y;} roughly becomes:
struct __lambda { int x; int operator()(int y) const { return x+y; } };
Real-world example
Understanding that a lambda is a class with captured members explains why capture-by-reference can dangle.
Templates
OOP & Classes
Lambda Expressions
std::function is a type-erased, general-purpose polymorphic wrapper that can hold any callable (lambda, function pointer, functor) matching a given signature. It's useful for storing lambdas in containers or class members where the exact closure type can't be named, at the cost of some overhead versus auto or templates.
std::function<int(int)> f = [](int x){ return x*x; };
std::vector<std::function<void()>> callbacks;
Real-world example
A UI framework stores button callbacks as std::function<void()> so any lambda can be registered.
Lambda Expressions
Templates
Lambda Expressions
Lambdas are most commonly used as inline callables for STL algorithms (sort comparators, predicates for find_if/count_if/remove_if, transformations), as callbacks and event handlers, in threading (passing work to std::thread or std::async), and anywhere a short, local function is clearer than a named one.
std::sort(v.begin(), v.end(),
[](int a, int b){ return a > b; }); // descending
Real-world example
A predicate lambda passed to std::remove_if filters out invalid records in one line.
STL
Concurrency
Lambda Expressions
C++14 init captures allow initializing a capture with an expression, including moving a move-only object into the closure: [p = std::move(ptr)]. This is needed to capture things like unique_ptr, which can't be copied, so the lambda takes ownership. It also lets you compute or rename captured values.
auto up = std::make_unique<int>(5);
auto f = [p = std::move(up)]() { return *p; }; // owns the unique_ptr
Real-world example
A task lambda takes ownership of a unique_ptr resource via move capture so it can run on another thread.
Move Semantics
RAII & Smart Pointers
Lambda Expressions