Capture by value

suggest change

If you specify the variable’s name in the capture list, the lambda will capture it by value. This means that the generated closure type for the lambda stores a copy of the variable. This also requires that the variable’s type be copy-constructible:

int a = 0;

[a]() {
    return a;   // Ok, 'a' is captured by value
auto p = std::unique_ptr<T>(...);

[p]() {         // Compile error; `unique_ptr` is not copy-constructible
    return p->createWidget(); 

From C++14 on, it is possible to initialize variables on the spot. This allows move only types to be captured in the lambda.

auto p = std::make_unique<T>(...);

[p = std::move(p)]() {
    return p->createWidget(); 

Even though a lambda captures variables by value when they are given by their name, such variables cannot be modified within the lambda body by default. This is because the closure type puts the lambda body in a declaration of operator() const.

The const applies to accesses to member variables of the closure type, and captured variables that are members of the closure (all appearances to the contrary):

int a = 0;

[a]() {
    a = 2;      // Illegal, 'a' is accessed via `const`

    decltype(a) a1 = 1; 
    a1 = 2; // valid: variable 'a1' is not const

To remove the const, you have to specify the keyword mutable on the lambda:

int a = 0;

[a]() mutable {
    a = 2;      // OK, 'a' can be modified
    return a;

Because a was captured by value, any modifications done by calling the lambda will not affect a. The value of a was copied into the lambda when it was constructed, so the lambda’s copy of a is separate from the external a variable.

int a = 5 ; 
auto plus5Val = [a] (void) { return a + 5 ; } ; 
auto plus5Ref = [&a] (void) {return a + 5 ; } ; 

a = 7 ; 
std::cout << a << ", value " << plus5Val() << ", reference " << plus5Ref() ;
// The result will be "7, value 10, reference 12"

Feedback about page:

Optional: your email if you want me to get back to you:

Table Of Contents