From my experience it seems that either:
- A lambda expression created inside a function call is destroyed just after the invocation
- Calling a function that expects a
std::functioncreates a temporary object (std::function) out of the lambda, and that object is destroyed after invocation
This behavior can be observed with the following snippet of code:
const function<void()>* pointer;
void a(const function<void()> & f)
{
pointer = &f;
}
void b()
{
(*pointer)();
}
int main()
{
int value = 1;
std::cout << &value << std::endl;
// 1: this works
function<void()> f = [&] () { std::cout << &value << std::endl; };
a(f);
// 2: this doesn't
a([&] () { std::cout << &value << std::endl; });
/* modify the stack*/
char data[1024];
for (int i = 0; i < 1024; i++)
data[i] = i % 4;
b();
return 0;
}
What exactly s actually happening in the second case?
Is there a correct way to call a() without creating an explicit std::function object?
Edit::
This both versions (1 and 2) compile just right but result in different outputs:
Version 1:
0x7fffa70148c8
0x7fffa70148c8
Version 2:
0x7fffa70148c8
0
If you create a temporary, it will be gone at the end of the line. This means storing a pointer to it is a bad idea, as you correctly stated.
If you want to store a pointer to a
std::function(or anything else really), you need to make sure it’s lifetime doesn’t end before you stop using the pointer. This means that you really do need a named object of typestd::function.As to what is happening in the second case: You create a temporary lambda to be passed to the function. Since the function expects a
std::function, a temporarystd::functionwill be created from the lambda. Both of those will be destroyed at the end of the line. Therefore you now have a pointer to an already destroyed temporary, which means that trying to use the pointed to object will bring you firmly into undefined behaviour territory.