Lambda Capture by Value vs Reference in C++: Key Differences and Usage
lambda capture by value copies variables into the lambda, preserving their values at capture time, while capture by reference lets the lambda access the original variables, reflecting any changes made after capture. Use capture by value to keep a snapshot of variables, and capture by reference to work with their current state.Quick Comparison
This table summarizes the main differences between lambda capture by value and by reference in C++.
| Aspect | Capture by Value | Capture by Reference |
|---|---|---|
| Variable Access | Copies variables into lambda | Uses original variables by reference |
| Variable Changes After Capture | Not reflected inside lambda | Reflected inside lambda |
| Safety | Safer, no dangling references | Risk of dangling references if variables go out of scope |
| Performance | May copy large objects (costly) | No copy, just reference (efficient) |
| Use Case | When you want a snapshot of values | When you want to modify or observe changes |
| Syntax Example | [x, y] | [&x, &y] |
Key Differences
Capture by value means the lambda makes its own copy of the variables it uses. This means the lambda keeps the values as they were when it was created, even if the original variables change later. This is useful when you want to preserve the state at capture time and avoid unexpected side effects.
On the other hand, capture by reference means the lambda uses the original variables directly. Any changes to those variables after the lambda is created will be visible inside the lambda. This allows the lambda to modify or observe the current state of variables, but it can be risky if the variables go out of scope before the lambda is called, causing undefined behavior.
Choosing between these depends on whether you want a stable snapshot of data (by value) or live access to variables (by reference). Also, copying large objects can be costly, so by reference can be more efficient but less safe.
Code Comparison
This example shows a lambda capturing variables by value. The lambda prints the copied values even if the originals change later.
#include <iostream> int main() { int x = 10; int y = 20; auto lambda_by_value = [x, y]() { std::cout << "Inside lambda by value: x = " << x << ", y = " << y << "\n"; }; x = 100; // change original variables y = 200; lambda_by_value(); return 0; }
Capture by Reference Equivalent
This example shows a lambda capturing variables by reference. The lambda reflects the updated values of the original variables.
#include <iostream> int main() { int x = 10; int y = 20; auto lambda_by_ref = [&x, &y]() { std::cout << "Inside lambda by reference: x = " << x << ", y = " << y << "\n"; }; x = 100; // change original variables y = 200; lambda_by_ref(); return 0; }
When to Use Which
Choose capture by value when you want the lambda to keep a fixed snapshot of variables at the time it is created, avoiding side effects from later changes. This is safer and good for multi-threading or when variables might go out of scope.
Choose capture by reference when you want the lambda to access or modify the current state of variables, reflecting any changes made after capture. Use this when performance matters and you are sure the variables will remain valid while the lambda runs.