From my experience it seems that either:
std::function
creates a temporary object (std::function) out of the lambda, and that object is destroyed after invocationThis 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 type std::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 temporary std::function
will 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.
It's okay for stateless lambdas. Stateless lambdas have an implicit conversion to function pointer type.
Also, there is always an implicit conversion to std::function<> regardless of the actual callable type.
There are problems with keeping a pointer to temporaries, though. I hadn't noticed that on first reading of the code.
That has nothing to do with std::function, of course.
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