6

绑定函数(使用 Boost Bind)时是否有任何性能影响(正面或负面)?

4

2 回答 2

11

也许,也许不是。这取决于。

std::bind(or also )的结果boost::bind是所谓的“绑定表达式”,它具有由实现确定的不可知类型。这种类型是Callable,它可以转换std::function(or boost::function) 的实例。

在内部,function(可能)使用类型擦除来处理各种复杂的、有状态的“可调用对象”。在某些(尽管不一定是所有)情况下,这需要动态分配和虚拟分派。两者bindfunction都是有状态的,因为它们存储绑定的参数。

结果是您应该尽可能避免将绑定表达式转换为function对象。绑定表达式本身可能更便宜,并且您不应该害怕使用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();
}
于 2012-09-16T12:11:04.643 回答
9

boost::bind并将std::bind复制它们的参数,以便返回的对象包含每个参数的副本,包括函数对象。如果这些参数的复制成本很高,那么将它们传递给std::bind.

您可以将其与创建所有参数的元组类似地考虑,例如

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

在性能上应该大致相当于:

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

如果您不想复制参数,请使用ref实用程序将它们传递给 areference_wrapper这是一种非常轻量级的类型,用于存储指向对象的指针:

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

当调用绑定函数时,每个绑定参数将作为左值传递给绑定函数(即没有完美转发):

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诸如占位符和调用嵌套绑定表达式等特性,但这些并不影响性能,以上所有内容仍然适用。

于 2013-01-14T01:25:34.197 回答