Lambda expressions were introduced in C++11 to allow the definition of small, anonymous functions directly at the point of use. One of the most important features of lambdas is the capture clause, which controls how variables from the surrounding scope are accessed inside the lambda body.
Before exploring the Lambda Capture clauses make sure you are familiar with Lambda Expressions in C++.
Lambda Capture Clauses in C++
The general syntax for a lambda expression is as follows:
[ capture_clause ] (parameters) -> return-type
{
definition of method
}
- The capture clause is specified inside square brackets []
- It determines how external variables are accessed inside the lambda
There are three ways to capture external variables using the Lambda Capture clauses
- Capture by reference
- Capture by value
- Capture by both reference and value (mixed capture)
Note: A lambda with an empty capture clause [ ] can only access variables which are local to it.
Examples of Lambda Captures
Example 1: Capture Values by Reference
In the following example, we will see how we can capture an external variable by reference so that the lambda function can modify the original variable.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vec = {10, 20, 30, 40, 50};
auto lambda = [&vec]() {
for (int& num : vec) {
num *= 10;
}
};
lambda();
for (int num : vec) {
cout << num << " ";
}
return 0;
}
Output
100 200 300 400 500
Explanation:
- &vec captures the vector by reference
- Changes inside the lambda affect the original vector
Example 2: Capture by Value
In the following example we will see how we can capture an external variable by value, which will create a copy of each variable inside the lambda function and the original value won't be affected.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vec = {10, 20, 30, 40, 50};
auto lambda = [vec]() {
for (int num : vec) {
cout << num * 10 << " ";
}
};
lambda();
cout << "\nOriginal vector: ";
for (int num : vec) {
cout << num << " ";
}
return 0;
}
Output
100 200 300 400 500 Original vector: 10 20 30 40 50
Explanation:
- vec is copied into the lambda
- Modifications do not affect the original vector
Example 3: Capture Values by both Reference and Value(Mixed)
In the following example, we will see how we can capture multiple external variables by both value and reference present outside the scope of the lambda function.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vec1 = {10, 20, 30, 40, 50};
vector<int> vec2 = {1, 2, 3, 4, 5};
auto lambda = [&vec1, vec2]() {
for (int& num : vec1) {
num *= 10;
}
for (int num : vec2) {
cout << num * 10 << " ";
}
cout << endl;
};
lambda();
cout << "Vector 1: ";
for (int num : vec1) cout << num << " ";
cout << "\nVector 2: ";
for (int num : vec2) cout << num << " ";
return 0;
}
Output
10 20 30 40 50 Vector 1: 100 200 300 400 500 Vector 2: 1 2 3 4 5
Explanation:
- vec1 is captured by reference, so its values change
- vec2 is captured by value, so original data remains unchanged