Подтвердить что ты не робот

Размер std:: function <void (int &)> type

Какая магия делает std::function<void(int&)> из С++ 11, что ее sizeof = 32? Если бы я сохранил ссылку на функцию в качестве указателя, она стоила бы всего 8 bytes (на 64-битной машине).

4b9b3361

Ответ 1

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

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

Ответ 2

std::function действительно волшебный, поскольку он может быть построен из любого вызываемого объекта! Он с радостью сохранит любое количество состояний для вас, даже если на поверхности вы сохраните ничтожную подпись void(int&).

Конечно, цена, связанная с этой магией, обычно использует своеобразное стирание типа (то есть динамическое распределение и виртуальную отправку) внутри. Детали меняются, но результирующие объекты, безусловно, "тяжелые" -— поэтому их следует избегать в пользу auto и шаблонов, когда это возможно!