C ++ Boost Bind Performance

Есть ли какое-либо влияние на производительность (положительное или отрицательное) при связывании функций (используя Boost Bind)?

6

Решение

Может быть, не может быть. Это зависит.

Результат std::bind (или также boost::bind) — это так называемое «выражение привязки», которое имеет непознаваемый тип, определяемый реализацией. Этот тип подлежащий выкупу, и это конвертируемый к примеру std::function (или же boost::function).

Внутренне function (может) использовать стирание типа для обработки различных сложных, вызываемых состоянием «вызываемых объектов». Это влечет за собой динамическое распределение и виртуальную диспетчеризацию в некоторых (хотя и не обязательно во всех) случаях. И то и другое bind а также function с состоянием, так как они хранят связанные аргументы.

В результате вы должны избегать преобразования выражения связывания в function возражать, если это возможно. Само выражение bind может быть дешевле, и вы не должны бояться использовать bind (например, при привязке указателей на функции-члены к экземплярам и аргументам). использование bind свободно, но преобразование в function только если вам действительно нужно управлять разнородной коллекцией вызываемых объектов.

Вот два типичных примера:

Плохой; Избегайте этого:

std::function<int(bool, char)> f = std::bind(&Foo::bar, x, 12);

void do_something(std::function<int()> func, int & acc)
{
acc += func();
}

Лучше; предпочитаю это:

auto f = std::bind(&Foo::bar, x, 12);   // unknowable type, but perfectly fine

template <typename F>
void do_something(F && func, int & acc)  // can deduce unknowable types
{
acc += func();
}
11

Другие решения

boost::bind а также std::bind будет копировать свои аргументы так, чтобы возвращаемый объект содержал копию каждого аргумента, включая объект функции. Если эти аргументы дороги для копирования, то будет дорого передать их std::bind,

Вы можете думать об этом аналогично созданию кортежа всех аргументов, например,

auto b = std::bind(func, arg1, arg2, arg3);

должен быть примерно эквивалентен по производительности:

auto b = std::make_tuple(func, arg1, arg2, arg3);

Если вы не хотите копировать аргументы, используйте ref утилита для передачи их в reference_wrapper это очень легкий тип, который хранит указатель на объект:

auto b = std::bind(func, std::ref(arg1), arg2, arg3);

При вызове связанной функции каждый из связанных аргументов будет передан связанной функции в виде lvalues ​​(т.е. без идеальной пересылки):

b();  // equiv to std::get<0>(b)(std::get<1>(b), std::get<2>(b), std::get<3>(b))

Если функция принимает свои аргументы по значению, то связанные аргументы будут скопированы в аргументы функции. Это может быть дорого, но это точно так же, если вы вызываете функцию напрямую или вызываете ее в результате std::bind … это свойство вызываемой функции, а не выражение привязки.

Таким образом, единственные накладные расходы на использование boost::bind находится в начальном копировании связанных аргументов, которыми вы можете управлять, перемещая аргументы во избежание копирования:

auto b = std::bind(func, std::move(arg1), arg2, arg3);

или передавая их по ссылке:

auto b = std::bind(func, std::ref(arg1), arg2, arg3);

Приведенное выше обсуждение игнорирует особенности bind такие как заполнители и вызов вложенных выражений связывания, но они не влияют на производительность, и все вышеперечисленное все еще применяется.

9