Consider the following snippet:
#include
#include
#include
int main()
{
std::vectorv = {
The return type of a lambda uses the auto return type deduction rules, which strips the referenceness. (Originally it used a slightly different set of rules based on lvalue-to-rvalue conversion (which also removed the reference), but that was changed by a DR.)
Hence, [&v](int i) { return v[i];}; returns int. As a result, in std::function, calling f() returns a dangling reference. Binding a reference to a temporary extends the lifetime of the temporary, but in this case the binding happened deep inside std::function's machinery, so by the time f() returns, the temporary is gone already.
g(3) is fine because the const int & returned is bound directly to the vector element v[i], so the reference is never dangling.