Reputation: 8757
I'm confused about the nature of the variable capture part of a lambda expression.
void f1();
std::function<int()> f2;
int main() {
f1();
std::cout<<f2()<<endl;
}
void f1() {
int x;
f2 = [&]() {
return x;
};
}
Isn't x
deconstructed before f2
is called?
Upvotes: 0
Views: 1225
Reputation: 168876
Isn't x deconstructed before f2 is called?
Yes, it is. Which means that the return x
evaluates a dangling reference, which invokes undefined behavior.
In this instance, you might prefer to capture by value.
f2 = [x]() { return x; }
Upvotes: 2
Reputation: 275956
Yes. You have successfully invoked undefined behavior. One possible outcome is that you get the value of x. Another is that the computer formats your hard drive, the program crashes, or the computer transforms into a robotic baker-assassin that feeds you cupcakes, mistakenly thinking you have celiac disease.
A safe variant of this might be:
int main() {
f1(7);
std::cout<<f2()<<endl;
}
void f1(int x) {
std::shared_ptr<int> spX( new int(x) );
f2 = [=]() {
return *spX;
};
}
or
void f1(int x) {
f2 = [=]() {
return x;
};
}
(for an int, there is little reason not to store it by value: for a more complex type, you might want to avoid copying it around needlessly).
Note that the comment above explains this in a funnier way.
Now, some compilers will mark the stack with special values when you decrement it to catch exactly this kind of undefined behavior (and by catch, I mean make it more obvious to the programmer). But for the most part, invoking undefined behavior in C++ is possible.
Upvotes: 4