C++ Lambda Captures
A lambda capture brings an outside value into a lambda. A capture copies the value or refers to the live variable.
Capture by value keeps the old value
The lambda copies limit when it is made. The original changes afterwards and the lambda still prints the copied value.
#include <iostream>
int main() {
int limit = 10;
auto show = [limit] {
std::cout << "Limit inside: " << limit << "\n";
};
limit = 20;
show();
std::cout << "Limit outside: " << limit << "\n";
return 0;
}Capture by reference changes the variable
The add lambda refers to the live total. Its change is still there after the call.
#include <iostream>
int main() {
int total = 5;
auto add = [&total](int amount) {
total = total + amount;
};
std::cout << "Before: " << total << "\n";
add(7);
std::cout << "After: " << total << "\n";
return 0;
}Default captures for a group
One lambda captures both values by value with [=]. Another captures both by reference with [&] and scales them.
#include <iostream>
int main() {
int width = 3;
int height = 4;
auto sum = [=] {
return width + height;
};
auto scale = [&](int factor) {
width = width * factor;
height = height * factor;
};
std::cout << "Sum: " << sum() << "\n";
scale(10);
std::cout << "Width: " << width << "\n";
std::cout << "Height: " << height << "\n";
return 0;
}A mutable counter lambda
The counter lambda holds its own copy of count. Each call raises the copy while the outside variable stays at zero.
#include <iostream>
int main() {
int count = 0;
auto counter = [count]() mutable {
count = count + 1;
std::cout << count << "\n";
};
counter();
counter();
counter();
std::cout << "Outside: " << count << "\n";
return 0;
}Example
#include <iostream>
int main() {
int rate = 10;
int total = 250;
auto applyDiscount = [rate, &total] {
total = total - total * rate / 100;
};
applyDiscount();
std::cout << "Total: " << total << "\n";
std::cout << "Rate: " << rate << "\n";
return 0;
}Key points
- A capture by value copies the value at the moment the lambda is made.
- Later changes to the original do not reach a by-value copy.
- A capture by reference refers to the live variable itself.
- Changes made through a by-reference capture stay after the call.
- A default capture written [&] captures by reference and [=] captures by value.
- The mutable keyword lets a lambda change its own by-value copies.
- A change to a copy still leaves the original variable untouched.
In this example, the discount lambda reads rate from a by-value capture. It changes total through a by-reference capture. The total prints 225 after the call.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
A lambda captures a variable by value and the original changes afterwards. What does the lambda see?