I'm using Visual Studio 2010, which apparently has some buggy behavior on lambdas, and have this nested lambda, where the inner lambda returns a second lambda wrapped as a std::function (cf. "Higher-order Lambda Functions" on MSDN):
int x = 0;
auto lambda = [&]( int n )
{
return std::function<void()>(
[&] // Note capture
{
x = n;
}
);
};
lambda( -10 )(); // Call outer and inner lambdas
assert( -10 == x ); // Fails!
This compiles but fails at the assert. Specifically, n in the inner lambda is uninitialized (0xCCCCCCCC), but x is successfully modified to its value. If I change the inner lambda's capture clause to "[&,n]", the assert passes as expected. Is this a bug with VS2010 or have I not understood how lambda capture works?
It is not a bug, since n
goes out of scope after lambdas return statement, thus the capture by reference is invalidated by the time you use it.
int x = 0;
auto lambda = [&]( int n )
{
return std::function<void()>( // n is local to "lambda" and is destroyed after return statement, thus when you call the std::function, the reference capture of n is invalid.
[&]
{
x = n; // Undefined behaviour
}
);
};
auto tmp = lambda(-10);
// n is no longer valid
tmp(); // calling tmp which uses reference of n which is alrdy destroyed.
assert( -10 == x ); // Fails!
This is similar to the case of just returning a simple reference. The thing that caught you was the compiler did not issue an warning. So it is not a bug in the compiler, it is just a lack of a warning.
std::function<int()> F(int n)
{
return [&]{ return n; }; //no warning
}
int& F2(int n)
{
return n; //warning
}
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