C ++提升绑定性能

时间:2012-09-16 11:46:00

标签: c++ performance boost c++11 boost-bind

绑定功能时是否存在性能影响(正面或负面)(使用Boost Bind)?

2 个答案:

答案 0 :(得分:11)

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

std::bind(或boost::bind)的结果是所谓的“绑定表达式”,其具有由实现确定的不可知类型。此类型是 Callable ,它是可转换std::function(或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();
}

答案 1 :(得分:9)

boost::bindstd::bind将复制其参数,以便返回的对象包含每个参数的副本,包括函数对象。如果复制这些参数的代价很高,那么将它们传递给std::bind会很昂贵。

您可以像创建所有参数的元组一样考虑它,例如

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

应该与性能大致相同:

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

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

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

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

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