Why can't I capture this link ('& this') in lambda?

I understand that the correct way to capture this (to change the properties of an object) in lambda is as follows:

 auto f = [this] () { /* ... */ }; 

But I am interested in the following feature that I saw:

 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 fuzziness that confused me (and I would like to answer) is as follows:

 auto f = [&] () { /* ... */ }; // capture everything by reference 

And why can't I explicitly write this at the link:

 auto f = [&this] () { /* ... */ }; // a compiler error as seen above. 
+60
c ++ lambda c ++ 11
May 01 '13 at 17:19
source share
2 answers

The reason [&this] does not work because it is a syntax error. Each parameter, separated by commas, in lambda-introducer is equal to capture :

 capture: identifier & identifier this 

You can see that &this not allowed syntactically. The reason this is unacceptable is because you will never want to grab this by reference, as this is a small const pointer. You would only want to pass it by value - therefore, the language simply does not support capturing this by reference.

To capture this explicitly, you can use [this] as a lambda-introducer .

The first capture can be capture-default , which:

 capture-default: & = 

This means that you automatically capture everything that I use by reference ( & ) or by value ( = ) respectively - however, this treatment is special - in both cases it is fixed by value for the above reasons earlier (even with the default capture & , which usually means capturing by reference).

5.1.2.7/8:

To search for the name (3.4), determining the type and value of this (9.3.2) and converting id expressions related to non-stationary members of the class to expressions for accessing the members of the class using (*this) (9.3.1), the compound operator [ OF LAMBDA] is considered in the context of a lambda expression.

So, the lambda acts as if it were part of an incoming member function using member names (for example, using the name x in your example), so it will generate "implicit usages" of this , like a member function does.

If the lambda capture includes a default capture, i.e. & , the identifiers in the lambda capture should not be preceded by & . If a lambda capture includes a default capture value of = , the lambda capture must not contain this , and each identifier it contains is preceded by & . The identifier or this should not be displayed more than once in a lambda capture.

So you can use [this] , [&] , [=] or [&,this] as a lambda-introducer to grab the this pointer by value.

However, [&this] and [=, this] poorly formed. In the latter case, gcc gratefully warns for [=,this] that explicit by-copy capture of 'this' redundant with by-copy capture default , and not errors.

+81
May 01 '13 at 17:24
source share

Since the Captures list is not &this :

N4713 8.4.5.2 Grips:

 lambda-capture: capture-default capture-list capture-default, capture-list capture-default: & = capture-list: capture...opt capture-list, capture...opt capture: simple-capture init-capture simple-capture: identifier &identifier this * this init-capture: identifier initializer &identifier initializer 
  1. For lambda capture purposes, the expression potentially references local objects as follows:

    7.3 This expression potentially refers to this.

Thus, the standard guarantees this and *this valid, and &this is not valid. Also, capturing this means capturing *this (which is the lvalue value, by the object itself) by reference , rather than capturing this pointer by value

+2
Dec 06 '17 at 16:00
source share



All Articles