Можно ли заменить std::function
каким-то другим объявлением, которое бы получало вывод std::bind
напрямую по значению, тем самым избегая динамического выделения памяти?
Да, это так; но тип, возвращаемый std::bind
, не указан, поэтому вам нужно будет использовать шаблон для захвата типа;
template <typename F>
void runThisFunction(F func);
О распределении памяти...
В этом вызове выходные данные std::bind
преобразуются в std::function
, и динамическое выделение памяти происходит как часть этого процесса.
Можно использовать динамическую память (но не всегда), это зависит от размера функтора, связанного с std::function
, и качество реализации.
Кроме того, в спецификации C++ есть этот §20.12.12.2.1/11. а>;
[Примечание: реализациям рекомендуется избегать использования динамически выделяемой памяти для небольших вызываемых объектов, например, где f
— это объект, содержащий только указатель или ссылку на объект и указатель на функцию-член. — примечание в конце]
Я бы не слишком беспокоился о распределении памяти, даже если оно есть. Если код не критичен к производительности и вы не измеряли его как таковой, требуемая косвенность не должна быть проблемой.
Имейте в виду, что в вашем случае foo
, привязанный к bind
, является указателем, и вполне вероятно, что в любом случае не будет динамического выделения памяти.
Я начал смотреть на это, потому что я измерял промахи кеша при преобразовании из-за неожиданной медлительности, обнаруженной с помощью инструментов.
Итак, у вас есть определенные опасения по поводу производительности... есть альтернативы использованию std::bind
в паре с std::function
. std::bind
полезное связующее общего назначения, но это не значит, что оно будет достаточно эффективным - сделайте свое собственное. Пользовательский функтор может быть более производительным. Реализация на основе лямбда также была бы полезна. Не забывайте также, что функцию foo
можно использовать и с std::function
, и тогда вы полностью отказываетесь от функтора/биндера (осторожно, сигнатуры должны совпадать).
Небольшое примечание о том, насколько «маленьким» должен быть объект, чтобы оптимизация «маленького объекта», упомянутая в приведенной выше цитате, вступила в силу, по-видимому, немного различается в зависимости от реализации библиотеки.
Здесь на coliru (libstdc++) размер аргумента для std::function
должен быть 16 байт или меньше, на MSVC ограничение составляет 32 байта (обе эти платформы выглядят как 32-разрядные платформы) . С 64-битной компиляцией clang++ (libc++) это ограничение составляет 24 байта... Это действительно зависит от реализации, сколько места они будут выделять, прежде чем необходимо будет сделать new
распределения.
Я не уверен, насколько критична производительность, но вычисление этого предела для ваших целей также может быть выполнено, а затем применена оптимизация, чтобы аргументы для std::function
оставались ниже этих пределов; например используя указатель или ссылку (также std::ref
) на struct
для аргументов (но нужно следить за тем, чтобы они не оставались висящими).
person
Niall
schedule
14.04.2016
template <class T> void runThisFunction(T func)
считается? - person Piotr Skotnicki   schedule 14.04.2016void runThisFunction(decltype(std::bind(foo, 1, 2))& func);
— я подозреваю, что вы сможете вызывать его с любым вызовомstd::bind()
, где статические типы аргументов соответствуютfoo
,1
и2
, но вам придется покопаться в Стандарте, чтобы убедиться, что это гарантировано. - person Tony Delroy   schedule 14.04.2016