
Modern C++ programming (especially from C++11 onward) embraces lambda expressions as a concise and powerful way to define anonymous functions, especially when working with STL algorithms, event handling, or asynchronous operations. One essential feature that makes lambdas so versatile is lambda capture.
Lambda capture allows a lambda expression to access variables from the scope in which it is defined. This feature bridges the gap between local context and functional programming, enabling powerful inline function customization in a clean and readable way.
๐ What is Lambda Capture?
In C++, lambda capture refers to the mechanism that allows a lambda function to access variables defined outside its body, within its surrounding lexical scope.
When you define a lambda, you can capture variables by value, by reference, or via the this pointer, using a capture clause.
๐ Lambda Syntax:
[capture_clause](parameter_list) -> return_type {
// function body
};
Capture Clause Examples:
[=]captures all external variables by value[&]captures all external variables by reference[x]captures variablexby value[&x]captures variablexby reference[=, &y]captures everything by value, exceptyby reference[this]captures the this pointer for use in class methods
๐ก Major Use Cases of Lambda Capture
1. STL Algorithms
Lambdas with captures are widely used in functions like std::sort, std::for_each, and std::find_if.
int offset = 5;
std::vector<int> vec = {1, 2, 3};
std::transform(vec.begin(), vec.end(), vec.begin(),
[offset](int val) { return val + offset; });
2. Event Handling and Callbacks
In GUI apps or frameworks (e.g., Qt, GTK), lambdas capture external state for button clicks or signals.
3. Threading and Concurrency
Use lambdas with capture to pass tasks to threads without global variables.
std::thread t([x]() { std::cout << x; });
4. Closures and Custom Scopes
Simulate closures by capturing context within a lambda.
5. Stateful Functional Programming
Define functions that remember a context or counter between calls by capturing variables by reference or mutable by value.
๐ How Lambda Capture Works (Architecture Overview)

Internally, a lambda with capture in C++ is compiled as a functor (a class with an overloaded operator()), where the captured variables become data members of that functor object.
๐งฉ Architecture Details:
| Component | Description |
|---|---|
| Lambda Object | Compiler-generated class that holds captured variables |
| Captured Variables | Stored as class members (by copy or reference) |
| operator()() | Member function implementing the lambda body |
| Capture Clause | Defines what variables are stored and how |
๐ Example Translation:
int x = 10;
auto lambda = [x]() { return x + 1; };
is similar to:
class Lambda {
int x;
public:
Lambda(int x_val) : x(x_val) {}
int operator()() const { return x + 1; }
};
๐ Basic Workflow of Lambda Capture
๐ก Logical Steps:
- Declare external variables in scope
- Define a lambda expression with a capture clause
- Capture needed variables by value or reference
- Call or pass the lambda to another function
- Compiler wraps the lambda into a callable object with context
๐ Step-by-Step Getting Started Guide for Lambda Capture
๐งฐ Step 1: Set Up a C++ Project
Use any modern C++ IDE (Code::Blocks, Visual Studio, CLion) or compile with g++ (C++11 and up).
g++ -std=c++17 lambda_example.cpp -o lambda_example
๐๏ธ Step 2: Write a Simple Lambda with Capture
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
int multiplier = 3;
std::vector<int> nums = {1, 2, 3};
std::for_each(nums.begin(), nums.end(), [multiplier](int n) {
std::cout << n * multiplier << " ";
});
}
โ Output: 3 6 9
๐ง Step 3: Use Mutable Lambdas for Modification
int counter = 0;
auto lambda = [counter]() mutable {
counter++;
return counter;
};
std::cout << lambda(); // 1
std::cout << lambda(); // 2 (mutable enables modification)
๐ง Step 4: Capture by Reference
int sum = 0;
std::vector<int> nums = {1, 2, 3};
std::for_each(nums.begin(), nums.end(), [&sum](int n) {
sum += n;
});
std::cout << "Sum = " << sum << std::endl;
โ Output: Sum = 6
๐งช Step 5: Mixed Captures
int a = 5, b = 10;
auto lambda = [=, &b]() mutable {
b += 1; // by reference
a += 1; // copy, won't affect external a
};