Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why do we need to capture reference for a reference in lambda?

Consider this:

class TestLambda {
public:
    std::vector<char> data;
};

void test_lambda(TestLambda& obj) {
    [=]() mutable {
        obj.data.push_back(0x01);
    }();
}

int main() {
    TestLambda tst;
    tst.data.push_back(0x99);
    test_lambda(tst);

    // tst.data is unchanged at this point

    return 0;
}

After calling test_lambda what I expected was to see the change in tst.data, but this is not the case. To see the changes, I had to create lambda passing again a reference of obj, ie. [&obj]().

Why do we need this? I mean, again a reference?

obj is already a reference. Then, lambda is capturing obj by copying it. So, obj within the lambda itself is not a reference? Why?

Could somebody explain me this? Thank you.

like image 711
Mert Mertce Avatar asked Feb 09 '23 13:02

Mert Mertce


1 Answers

When used in the right hand side of an assigment, a reference works just as a "normal" variable. Whenever you define a lambda capturing by value, the lambda owns a copy of the outer variables, as if the lambda started with these lines:

auto my_inner_variable = my_outer_reference;
auto my_inner_other_variable = my_outer_other_variable;

If you want the reference to "remain" a reference, you have to capture it by reference, thus instructing the compiler to emit code like this:

auto& my_inner_variable = my_outer_reference;
auto& my_inner_other_variable = my_outer_other_variable; // if we instructed to capture everything by reference
like image 57
lodo Avatar answered Feb 11 '23 03:02

lodo