What kind of magic does the std::function<void(int&)>
from C++11 that its sizeof = 32
? If I'd store the function reference as a pointer, it'd cost only 8 bytes
(on a 64 bit machine).
Note that when talking about overhead of std::function (i.e. that std::function is "heavy"), usually the performance overhead is meant. Its memory overhead will be minor (around 2 extra pointers, I'd guess).
Instances of std::function can store, copy, and invoke any CopyConstructible Callable target -- functions, lambda expressions, bind expressions, or other function objects, as well as pointers to member functions and pointers to data members.
As it happens, std::function is guaranteed to not allocate if constructed from a function pointer, which is also one word in size. So constructing a std::function from this kind of lambda, which only needs to capture a pointer to an object and should also be one word, should in practice never allocate.
If it is small, like 3-5 CPU instructions then yes std::function will make it slower, because std::function is not inlined into outer calling code. You should use only lambda and pass lambda as template parameter to other functions, lambdas are inlined into calling code.
For std::function<Signature>
it is a trade-off between object size and allocation which is interesting: For small function objects it is desirable to avoid an allocation. On the other hand, doing so increases the object size. For the small function optimization to be useful and not introduce overheads when actually calling the object, the object size needs to be at least two pointers plus some memory to store simple function objects. It seems that a size of 32 bytes is exactly this (on a system where sizeof(T*)
is 8).
That is, internally a std::function<Signature>
object stores an inheritance hierarchy: The base class provides the interface to be called, delegating to a templatized derived which implements the call interface (plus, probably, some clone()
functionality). In an implementation optimized for size the function object would just keep a pointer to the base, but to avoid allocation it would set aside some internal storage to allocate the entire object in and point to this object (the internal pointer avoids a condition when actually calling the function object). The memory needed for the object is a virtual function pointer plus any data for the actual function object the std::function<Signature>
object is initialized with. To accommodate member functions with their object it seems that two more words is reasonably small.
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