If there is a lambda capture [=, &var] does it mean that it can access all the variables in the scope in which it is defined by value except for var? Also does [&var, =] mean the same thing?
If there is a lambda capture [=, &var] does it mean that it can access all the variables in the scope in which it is defined by value except for var?
Yes, except that if there is a current object, it (i.e. *this) is also captured by reference.
This is because if the current object is implicitly bound it always captured by reference. To capture the current object by value it must be explicitly captured by value: ([=, *this])
Also does [&var, =] mean the same thing?
No, because that's a syntax error. The capture-default must appear first in the capture list.
Aren’t all pointers captured as they are, i.e. pointers?
C++ has idiosyncratic rules about this in a lambda capture list. If the form this appears in a capture list, or it is captured implicitly, the members bound by the current object *this are visible in the closure, roughly like the lambda expression was a member function. Plain old this can only be captured by value (because the capture &this is a syntax error), and it allows transparent access to the members of the current object:
1 2 3 4
struct A {
int x = 0;
int f() { [this]() { return x++; }(); } // A::x is visible.
} a;
Each time you call a.f(), a.x is incremented again.
C++17 supplies a mechanism to copy the current object into the lambda by explicitly adding *this to the capture list:
# include <iostream>
struct A {
// Note: *this is captured by reference.
auto make_get_n_ref() { return [this](){ return n; }; }
// Note: *this is captured by value
auto make_get_n_val() { return [*this](){ return n; }; }
int n = 1;
};
int main() {
A a;
// the value that foo() will return is fixed at the
// point the closure was created
auto foo = a.make_get_n_val();
// the value that bar() will return depends on the value of a.n
// at the time of the call
auto bar = a.make_get_n_ref();
std::cout << foo() << ", " << bar() << '\n';
a.n = 2;
std::cout << foo() << ", " << bar() << '\n';
}
Uh, I see what you mean. Thanks a lot for your kind explanation, mbozzi, I didn’t know it was possible to capture the current object by copy (it sounds potentially expensive, anyway).