While std::function
is movable, in some cases it's not possible or not convenient. Is there a significant penalty for copying it?
Does it possibly depend on the size of the captured variables (if it was created using a lambda expression)? Is it implementation dependent?
std::function
is typically implemented as a value-semantics, small-buffer optimized, virtual-dispatch, type-erasing class.
This means if your state is small, a copy will involve no heap allocation (other than within the copy ctor of the state) and some indirection (to find how to copy this particular state).
If your state is large (larger than two std::string
s on current MSVC, for example), it requires an additional heap allocation to store the state.
This is not something you want to do on a per-pixel per-frame basis, but it isn't insanely expensive.
How your particular compiler and library version implements std::function
could vary, but I am unaware of any that differs significantly from the above.
So, in the following code:
std::function<std::string()> f = [s = "hello"s]{ return s; };
copying f
will involve 0 heap allocations on MSVC.
Whereas, this code:
std::function<std::string()> g = [a = "a"s, b = "b"s, c = "c"s]{ return a+b+c; };
does require a heap allocation to copy g
.
(And yes, both of these are really dumb function objects.)
There is an effective requirement that the small buffer optimization (SBO) be applied for certain cases (function pointers, member function pointers) in std::function
by the fact that they are expected not to fail at allocating memory. Once you have written one SBO case, making it more general isn't hard, so most std::function
implementations store small objects "inside themselves" and larger objects on the heap.
However, this threshold is not specified by the standard, and it is important for the performance cost, so if performance is really important, you'll have to profile to ensure that your implementation does it.
It is indeed implementation-dependent. It also depends on what exactly you are storing in the std::function
. It is surely not as cheap as simply copying a C-style function pointer.
The best thing would be for you to try writing the code the way you find clear and convenient, then, if it does not run quickly enough, profile it. If you need ultimate performance, you may find std::function
is not suitable at all.
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