This answer states that std::bind
returns an object by value, and this comment implies that assigning to std::function
will cause a heap allocation to store the value returned by std::bind
.
Is there a way to avoid this heap allocation and pass the return value of std::bind
to another function directly by value?
If so, what would the method signature replace std::function
with?
To be more explicit, I have a function like the following.
void runThisFunction(std::function<void()> func);
Suppose there is a function foo
with the following signature.
void foo(int a, int b);
Now, I would invoke runThisFunction
as follows.
runThisFunction(std::bind(foo, 1, 2));
In this invocation, the output of std::bind
is converted into an std::function
, and dynamic memory allocation occurs as part of this process.
Is it possible to replace std::function
with some other declaration that would would receive the output of std::bind
directly by value, thereby avoiding the dynamic memory allocation?
Is it possible to replace
std::function
with some other declaration that would would receive the output ofstd::bind
directly by value, thereby avoiding the dynamic memory allocation?
Yes it is; but the type returned by std::bind
is unspecified, so you will need to use a template to capture the type;
template <typename F>
void runThisFunction(F func);
On the memory allocation...
In this invocation, the output of
std::bind
is converted into anstd::function
, and dynamic memory allocation occurs as part of this process.
Dynamic memory may be used (but not always), it depends on the size of the functor being bound into the std::function
and the quality of implementation.
Further, the C++ spec has this §20.12.12.2.1/11;
[Note: Implementations are encouraged to avoid the use of dynamically allocated memory for small callable objects, for example, where
f
is an object holding only a pointer or reference to an object and a member function pointer. — end note ]
I would not be too concerned about the memory allocation even if there is one. Unless the code is performance critical and you have measured it as such, the indirection required should not be a problem.
Bear in mind that for your case, the foo
being bound in the bind
is a pointer and it is likely that there would be no dynamic memory allocation anyway.
I started looking at this because I measured cache misses on the conversion due to unexpected slowness detected through instrumentation
So you have some measured concerns about the performance... there are alternatives to using std::bind
paired with std::function
. std::bind
is useful general purpose binder, but that doesn't mean it will also be performant enough - make your own. A custom functor could be more performant. A lambda based implementation would also be good to look at. Don't forget either that the function foo
can be used with std::function
as well and then you forgo the functor/binder completely (caveat, the signatures need to match).
A side note on how "small" the object needs to be before the "small object" optimisations mentioned in the quote above kick in seems to vary between the library implementations quiet a bit.
Here on coliru (libstdc++), the size of the argument for std::function
needs to be 16 bytes or less, on MSVC, the limit is 32 bytes (both of these look to be 32-bit platforms). With a clang++ (libc++) 64-bit compile, this limit is 24 bytes... It really is up to the implementation how much space they will allow for before new
allocations need to be made.
I'm not sure how critical the performance is, but calculating this limit for your targets could also be done and then optimisations applied such that the arguments for the std::function
are kept below these limits; e.g. using a pointer or reference (also std::ref
) to a struct
for arguments (but care must be taken that these are not left dangling).