While playing around with references to lambdas I encountered a scenario where I expected the program to crash due to dangling references. In the following program, I assumed that the lambda argument to fn_x_3
in main
is "moved to" the fn_x_3
function because it's an rvalue, where it binds to the lvalue fn
.
#include <iostream>
#include <functional>
std::function<int(int)> fn_x_3(std::function<int(int, int)>& fn) {
// capture fn by reference!
return [&fn](int x) {
return fn(x, 3);
};
}
std::function<int(int)> fn_x_3(std::function<int(int, int)>&& fn) {
// passing fn (lvalue) by reference to fn_x_3 overload
return fn_x_3(fn);
}
int main()
{
// call to fn_x_3(function<int(int)>&& fn), lambda "moved into" the function
auto fn = fn_x_3([](int x, int y){ return x + y; });
int result = fn(2);
std::cout << result << std::endl;
return 0;
}
This program prints out 5
. But when fn
goes out of scope in fn_x_3(function<int(int,int)>&&)
, does this not invalidate the reference that is captured in fn_x_3(function<int(int,int)>&)
?
It does, pretty much second function overload fn_x_3 is ok BUT if you use the return value in any way outside the scope of the function you are invoking UB by using object past its lifetime (the object is the underlying lambda structure of first fn_x_3 overload).
It is not enforced by the C++ compiler to block compilation of such programs. If you want to find these kinds of error you could use so called address sanitizers.
Programs prints 5 - it is most likely due to the fact that the memory that you are accessing is still "bound" to the executable thus it doesn't see any access violations (std::function implementation detail)