I understand the correct way to capture this
(to modify object properties) in a lambda is as follows:
auto f = [this] () { /* ... */ };
But I'm curious as to the following peculiarity I've seen:
class C {
public:
void foo() {
// auto f = [] () { // this not captured
auto f = [&] () { // why does this work?
// auto f = [&this] () { // Expected ',' before 'this'
// auto f = [this] () { // works as expected
x = 5;
};
f();
}
private:
int x;
};
The oddity that I am confused by (and would like answered) is why the following works:
auto f = [&] () { /* ... */ }; // capture everything by reference
And why I cannot explicitly capture this
by reference:
auto f = [&this] () { /* ... */ }; // a compiler error as seen above.
Best Answer
The reason
[&this]
doesn't work is because it is a syntax error. Each comma-seperated parameter in thelambda-introducer
is acapture
:You can see that
&this
isn't allowed syntactically. The reason it isn't allowed is because you would never want to capturethis
by reference, as it is a small const pointer. You would only ever want to pass it by value - so the language just doesn't support capturingthis
by reference.To capture
this
explicitly you can use[this]
as thelambda-introducer
.The first
capture
can be acapture-default
which is:This means capture automatically whatever I use, by reference (
&
) or by value (=
) respectively - however the treatment ofthis
is special - in both cases it is captured by value for the reasons given previously (even with a default capture of&
, which usually means capture by reference).5.1.2.7/8:
So the lambda acts as if it is part of the enclosing member function when using member names (like in your example the use of the name
x
), so it will generate "implicit usages" ofthis
just like a member function does.So you can use
[this]
,[&]
,[=]
or[&,this]
as alambda-introducer
to capture thethis
pointer by value.However
[&this]
and[=, this]
are ill-formed. In the last case gcc forgivingly warns for[=,this]
thatexplicit by-copy capture of ‘this’ redundant with by-copy capture default
rather than errors.