Simple example:
class Foo {
int x;
void bar(int x) {
[this]() -> void {
x = 6;
}();
}
};
This doesn't compile on GCC, Clang, MVC, or ICC (see it live). If I change void bar(int x)
to void bar(int y)
, or if I change x = 6;
to this->x = 6;
then it works fine.
This doesn't make sense to me. The local variable x
from the call to bar
is deliberately not being captured in the lambda. The only x
that makes sense is Foo
's member variable.
Question: Is this the expected behavior, and iff so, please explain why?
To capture the member variables inside lambda function, capture the “this” pointer by value i.e. std::for_each(vec. begin(), vec. end(), [this](int element){ //.... }
A lambda expression can't define any new scope as an anonymous inner class does, so we can't declare a local variable with the same which is already declared in the enclosing scope of a lambda expression. Inside lambda expression, we can't assign any value to some local variable declared outside the lambda expression.
Yes, but instance variables can be referenced and assigned in a lambda, which is surprising to me. Only local variables have the final limitation.
From cppreference:
For the purpose of name lookup, determining the type and value of the this pointer and for accessing non-static class members, the body of the closure type's function call operator is considered in the context of the lambda-expression.
In the body of the method bar(int x), the token 'x' refers to the argument of the method, NOT to the member of the class. The member is hidden. [NOTE this is certainly poor coding practice, but not illegal]
If you were to say x = 6
where you currently have the lambda definition, you would expect the local variable x
(i.e. the passed-by-value-argument to the method) to be changed, not the member x
, right?
Thus the only question is can a local variable be implicitly captured by a lambda? I'd say the compilers are pretty clear in explaining that it cannot.
cppreference also makes this clear in this statement:
A variable can be used without being captured if it does not have automatic storage duration (i.e. it is not a local variable or it is static or thread local) or if it is not odr-used in the body of the lambda.
Note: odr-used means you have to know the address of a variable, not just its value. Assigning a value to a variable counts as odr-using it.
Consider this code:
class Foo {
int george;
void bar(int washington) {
int martha = washington;
washington = 7;
int jefferson = washington;
int adams = martha;
george = 6;
[this, jefferson]() -> void {
this->george = 15; // legal because `this` is captured
jefferson = adams; // legal because jefferson is explicitly
// captured, and because adams is not
// odr-used, so adams can be captured
// implicitly.
martha = 9; // not legal because it is an odr-use
// of a local variable so martha is not
// implicitly captured.
}();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With