Reputation: 687
I have trouble understanding lambda functions and the mechanism to capture variables, so I did a little testing and arrived at really weird conclusion. that is:
class ClassA
{
public:
std::function<void()> lambda;
void DoYourStuff()
{
int x;
x = 1;
lambda = [=] () { printf("A %d\n", x);};
lambda();
x = 2;
lambda();
}
};
class ClassB
{
public:
std::function<void()> lambda;
int x;
void DoYourStuff()
{
x = 1;
lambda = [=] () { printf("B %d\n", x);};
lambda();
x = 2;
lambda();
}
};
Note: only difference is in placement of x variable; ClassA and ClassB's functions have different output!
A 1
A 1
B 1
B 2
So my questions are:
Thanks
Upvotes: 6
Views: 289
Reputation: 254751
The first captures the local variable x
by value; so it prints 1
both times, since its copy hasn't changed.
The second captures the local quasi-variable this
, not the member variable x
. So the body is equivialent to printf("%d\n", this->x);
, and will print the new value of 2
after you change x
.
If you were to explicitly capture x
(i.e. [x](){...}
), then you will see the same result as the first.
Is this the desired behaviour?
It's the behaviour specified by the language standard.
if i used [&] instead of [=] in ClassA, would those lambdas be identical?
No, but both would produce the same output. The first would capture the local x
by reference, so you will see the change to it.
Is there some general rule as to when [=] actually makes copy?
Yes, it copies the variable when the lambda is created.
When exactly is the capturing of variables by lambdas supposed to happen?
When the lambda is created.
Can I force lambda to do a re-capture of variables?
No. Once it's captured by value, it has its own copy of the variable, with no way to access the original. If you need to see changes to the original, then capture by reference (and take care with object lifetimes).
Upvotes: 11