Ответ 1
Для std::function<Signature>
это компромисс между размером объекта и распределением, который интересен: для объектов с малой функцией желательно избегать выделения. С другой стороны, это увеличивает размер объекта. Чтобы оптимизация небольших функций была полезной и не вводила накладные расходы при фактическом вызове объекта, размер объекта должен быть как минимум двумя указателями плюс некоторая память для хранения простых объектов функции. Кажется, что размер 32 байта именно это (в системе, где sizeof(T*)
равно 8).
То есть внутри объекта std::function<Signature>
хранится иерархия наследования: базовый класс предоставляет интерфейс, который должен быть вызван, делегирование к производной templatized, которая реализует интерфейс вызова (плюс, возможно, некоторые функции clone()
). В реализации, оптимизированной для размера, объект-функция просто сохранит указатель на базу, но чтобы избежать выделения, он выделил бы некоторое внутреннее хранилище для размещения всего объекта в и указывал бы на этот объект (внутренний указатель избегает состояния при фактическом вызове объект функции). Память, необходимая для объекта, является указателем виртуальной функции плюс любые данные для фактического объекта функции, с которым инициализируется объект std::function<Signature>
. Чтобы разместить функции-члены с их объектом, кажется, что еще два слова достаточно малы.