When the outer variable x
is captured by value
return [=](int y){ return x * y; };
foo(2)(3)
produces 6
.
However if I capture x
by reference
return [&](int y){ return x * y; };
foo(2)(3)
produces 9
.
Minimal Code
#include <iostream>
#include <functional>
int main()
{
using namespace std;
function<function<int(int)>(int)> foo = [](int x)
{
return [&](int y) { return x * y; };
};
cout << foo(2)(3);
return 0;
}
Question
I cannot figure out why this happens, can you?
CodePudding user response:
x
is local to the outer function, so it's destroyed as soon as that function returns.
Consider a simpler example.
#include <iostream>
#include <functional>
int& foo(int x) {
return x;
}
int main()
{
using namespace std;
int& b = foo(5);
return 0;
}
Here it's easier to see that b
is a dangling reference.
Next we go ahead and instead of returning the reference directly, we return a lambda that captures the variable by reference.
#include <iostream>
#include <functional>
auto foo(int x) {
return [&x]() {return x;};
}
int main()
{
using namespace std;
auto b = foo(5);
return 0;
}
The problem still remains. Once the lambda is returned, x
has already gone out of scope and is no longer alive. But the lambda holds a (dangling) reference to it.
CodePudding user response:
When the lambda capture x
by-reference, when the invocation of foo(2)
ends, the parameter x
gets destroyed, then the reference captured to it becomes dangling. The dereference on it in the invocation of foo(2)(3)
leads to UB, anything is possible.
Capture-by-value doesn't have such invalid reference issue.