Why are member variables captured by an “all automatic” capture, but not by explicit naming?

  • A+
Category:Languages

In C++11 (from cppreference.com):

[&] captures all automatic variables used in the body of the lambda by reference and current object by reference if exists

And...

[a,&b] where a is captured by copy and b is captured by reference

So my question is, if we have a class such as (VERSION A):

class Foo {     public:      void test()     {         auto y = [&](){ return x; }();   // Line 6     }      int x;     }; 

In Line 6, we successfully capture the member variable x using the "all automatic variables by reference" capture specifier.

Or we can write (VERSION B):

{     int& x = this->x;     auto y = [&x](){ return x; }(); } 

But the following does not compile (VERSION C):

{     auto y = [&x](){ return x; }(); } 

This is because x does not exist as a name in the enclosing scope.

This also does not compile (VERSION D):

{     auto y = [&this](){ return x; }(); } 

This is because this cannot be captured by reference.

So, my question is, why does VERSION A work and not VERSION C or VERSION D? I understand why VERSION C and D do not work, but I don't understand why A works.

If we can't capture this by reference, and we cannot capture variables not in the parent scope, how is x being captured in VERSION A?

Intuitively, according to the capture rules VERSION B is the only version I'd expect to work.

 


Version A works because *this is implicitly captured by reference.

The current object (*this) can be implicitly captured if either capture default is present.

When you specify capture default (the [&] in this case), *this is implicitly captured; which has the same effect as [this]. Note that what's captured by reference is *this, not this itself; this can't be captured explicitly by reference like [&this], so version D fails.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: