According to the sources I have found, a lambda expression is essentially implemented by the compiler creating a class with overloaded function call operator and the referenced variables as members. This suggests that the size of lambda expressions varies, and given enough references variables that size can be arbitrarily large.
An std::function
should have a fixed size, but it must be able to wrap any kind of callables, including any lambdas of the same kind. How is it implemented? If std::function
internally uses a pointer to its target, then what happens, when the std::function
instance is copied or moved? Are there any heap allocations involved?
The implementation of
std::function
can differ from one implementation to another, but the core idea is that it uses type-erasure. While there are multiple ways of doing it, you can imagine a trivial (not optimal) solution could be like this (simplified for the specific case ofstd::function<int (double)>
for the sake of simplicity):In this simple approach the
function
object would store just aunique_ptr
to a base type. For each different functor used with thefunction
, a new type derived from the base is created and an object of that type instantiated dynamically. Thestd::function
object is always of the same size and will allocate space as needed for the different functors in the heap.In real life there are different optimizations that provide performance advantages but would complicate the answer. The type could use small object optimizations, the dynamic dispatch can be replaced by a free-function pointer that takes the functor as argument to avoid one level of indirection... but the idea is basically the same.
Regarding the issue of how copies of the
std::function
behave, a quick test indicates that copies of the internal callable object are done, rather than sharing the state.The test indicates that
f2
gets a copy of the callable entity, rather than a reference. If the callable entity was shared by the differentstd::function<>
objects, the output of the program would have been 5, 6, 7.