How is it possible that this example works? It prints 6
:
#include <iostream> #include <functional> using namespace std; void scopeIt(std::function<int()> &fun) { int val = 6; fun = [=](){return val;}; //<-- this } int main() { std::function<int()> fun; scopeIt(fun); cout << fun(); return 0; }
Where is the value 6
stored after scopeIt
is done being called? If I replace the [=]
with a [&]
, it prints 0
instead of 6
.
It is stored within the closure, which - in your code - is then stored within std::function<int()> &fun
.
A lambda generates what's equivalent to an instance of a compiler generated class.
This code:
[=](){return val;}
Generates what's effectively equivalent to this... this would be the "closure":
struct UNNAMED_TYPE { UNNAMED_TYPE(int val) : val(val) {} const int val; // Above, your [=] "equals/copy" syntax means "find what variables // are needed by the lambda and copy them into this object" int operator() () const { return val; } // Above, here is the code you provided } (val); // ^^^ note that this DECLARED type is being INSTANTIATED (constructed) too!!
Lambdas in C++ are really just "anonymous" struct functors. So when you write this:
int val = 6; fun = [=](){return val;};
What the compiler is translating that into is this:
int val = 6; struct __anonymous_struct_line_8 { int val; __anonymous_struct_line_8(int v) : val(v) {} int operator() () const { return val; // returns this->val } }; fun = __anonymous_struct_line_8(val);
Then, std::function
stores that functor via type erasure.
When you use [&]
instead of [=]
, it changes the struct to:
struct __anonymous_struct_line_8 { int& val; // Notice this is a reference now! ...
So now the object stores a reference to the function's val
object, which becomes a dangling (invalid) reference after the function exits (and you get undefined behavior).
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