Lambda Capture Clause in C++
In C++, lambda expressions were introduced after C++ 11 and allowed users to create a small inline function directly without declaring functions explicitly. In this article, we will discuss how we can use capture clauses in Lambda expressions to access variables from the enclosing scope of the expressions.
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
}
Here, capture clauses are defined inside the square brackets[].
Capture Clauses in lambda expressions determine how the external variables are accessed from the lambda expression. The capture clauses allow the lambda function to capture external variables and use them inside the lambda body.
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.
// C++ Program to Demonstrate Lambda Function capturing
// variable by reference
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> vec = { 10, 20, 30, 40, 50 };
cout << "Original vector before applying lambda "
"function: ";
for (int num : vec) {
cout << num << " ";
}
cout << endl;
// Capture vector values by reference using capture
// clauses
auto lambda = [&vec]() {
cout
<< "Vector values inside the lambda function: ";
for (int& num : vec) {
num *= 10;
cout << num << " ";
}
cout << endl;
};
// Call the lambda function
lambda();
// Print the original vector
// You will observe that the values of the original
// vector will be changed
cout << "Original vector after applying lambda "
"function: ";
for (int num : vec) {
cout << num << " ";
}
return 0;
}
// C++ Program to Demonstrate Lambda Function capturing
// variable by reference
using namespace std;
int main()
{
vector<int> vec = { 10, 20, 30, 40, 50 };
cout << "Original vector before applying lambda "
"function: ";
for (int num : vec) {
cout << num << " ";
}
cout << endl;
// Capture vector values by reference using capture
// clauses
auto lambda = [&vec]() {
cout
<< "Vector values inside the lambda function: ";
for (int& num : vec) {
num *= 10;
cout << num << " ";
}
cout << endl;
};
// Call the lambda function
lambda();
// Print the original vector
// You will observe that the values of the original
// vector will be changed
cout << "Original vector after applying lambda "
"function: ";
for (int num : vec) {
cout << num << " ";
}
return 0;
}
Output
Original vector before applying lambda function: 10 20 30 40 50 Vector values inside the lambda function: 100 200 300 400 500 Original vector after applying lambda function: 100 200 300 400 500
Example 2: Capture Values 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.
// C++ Program to Demonstrate Lambda Function Capturing
// Vector Values by Value
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> vec = { 10, 20, 30, 40, 50 };
// Capture vector values by value using capture clauses
auto lambda = [vec]() {
cout
<< "Vector values inside the lambda function: ";
for (int num : vec) {
num *= 10; // Make changes in the captured
// vector values
cout << num << " ";
}
cout << endl;
};
lambda(); // Call the lambda function
// Print the original vector
// You will observe no change in the original vector
// values as they were captured via values
cout << "Original vector after applying lambda "
"function: ";
for (int num : vec) {
cout << num << " ";
}
return 0;
}
// C++ Program to Demonstrate Lambda Function Capturing
// Vector Values by Value
using namespace std;
int main()
{
vector<int> vec = { 10, 20, 30, 40, 50 };
// Capture vector values by value using capture clauses
auto lambda = [vec]() {
cout
<< "Vector values inside the lambda function: ";
for (int num : vec) {
num *= 10; // Make changes in the captured
// vector values
cout << num << " ";
}
cout << endl;
};
lambda(); // Call the lambda function
// Print the original vector
// You will observe no change in the original vector
// values as they were captured via values
cout << "Original vector after applying lambda "
"function: ";
for (int num : vec) {
cout << num << " ";
}
return 0;
}
Output
Vector values inside the lambda function: 100 200 300 400 500 Original vector after applying lambda function: 10 20 30 40 50
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.
// C++ Program to Demonstrate Lambda Function Capturing
// Vector Values by Reference and Value
#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 };
cout << "Original vectors before applying lambda "
"function:"
<< endl;
cout << "Values of vector 1: ";
for (int num : vec1) {
cout << num << " ";
}
cout << endl;
cout << "Values of vector 2: ";
for (int num : vec2) {
cout << num << " ";
}
cout << endl;
cout << endl;
// Capture vector 1 values by reference and vector 2
// values by value
auto lambda = [&vec1, vec2]() {
cout << "Vector values inside the lambda function:"
<< endl;
cout << "Values of vector 1: ";
for (int& num : vec1) {
num *= 10; // Make changes in the captured
// vector1 values
cout << num << " ";
}
cout << endl;
cout << "Values of vector 2: ";
for (int num : vec2) {
num *= 10; // Make changes in the captured
// vector2 values
cout << num << " ";
}
cout << endl;
};
lambda(); // Call the lambda function
cout << endl;
cout << "Original vectors after applying lambda "
"function:"
<< endl;
cout << "Values of vector 1: ";
for (int num : vec1) {
cout << num << " ";
}
cout << endl;
cout << "Values of vector 2: ";
for (int num : vec2) {
cout << num << " ";
}
return 0;
}
// C++ Program to Demonstrate Lambda Function Capturing
// Vector Values by Reference and Value
using namespace std;
int main()
{
vector<int> vec1 = { 10, 20, 30, 40, 50 };
vector<int> vec2 = { 1, 2, 3, 4, 5 };
cout << "Original vectors before applying lambda "
"function:"
<< endl;
cout << "Values of vector 1: ";
for (int num : vec1) {
cout << num << " ";
}
cout << endl;
cout << "Values of vector 2: ";
for (int num : vec2) {
cout << num << " ";
}
cout << endl;
cout << endl;
// Capture vector 1 values by reference and vector 2
// values by value
auto lambda = [&vec1, vec2]() {
cout << "Vector values inside the lambda function:"
<< endl;
cout << "Values of vector 1: ";
for (int& num : vec1) {
num *= 10; // Make changes in the captured
// vector1 values
cout << num << " ";
}
cout << endl;
cout << "Values of vector 2: ";
for (int num : vec2) {
num *= 10; // Make changes in the captured
// vector2 values
cout << num << " ";
}
cout << endl;
};
lambda(); // Call the lambda function
cout << endl;
cout << "Original vectors after applying lambda "
"function:"
<< endl;
cout << "Values of vector 1: ";
for (int num : vec1) {
cout << num << " ";
}
cout << endl;
cout << "Values of vector 2: ";
for (int num : vec2) {
cout << num << " ";
}
return 0;
}
Output
Original vectors before applying lambda function:
Values of vector 1: 10 20 30 40 50
Values of vector 2: 1 2 3 4 5
Vector values inside the lambda function:
Values of vector 1: 100 200 300 400 500
Values of vector 2: 10 20 30 40 50
Original vectors after applying lambda function:
Values of vector 1: 100 200 300 400 500
Values of vector 2: 1 2 3 4 5
In the following example, vector 1 was passed as a reference, and vector 2 was passed as a value. You can observe that inside the lambda function, the values of both vectors were changed as their values were captured by the Capture clauses. But outside the lambda function, the original value of vector 1 was changed as it was passed via reference but the original values of vector 2 remained the same as it was passed by value.
Conclusion
In the following article, we have discussed how we can use capture clauses along with the lambda expressions in C++. We have discussed various ways through which we can capture external variables in the lambda function which are outside its scope. Please note that if you capture values by reference then the changes will be made to the original data. If you only want to change the values inside the lambda function then use the capture-by-value method so that the original values won't be affected.