C++提升绑定性能

tro*_*ana 6 c++ performance boost boost-bind c++11

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

Ker*_* SB 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();
}
Run Code Online (Sandbox Code Playgroud)

更好; 喜欢这个:

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();
}
Run Code Online (Sandbox Code Playgroud)


Jon*_*ely 9

boost::bind并且std::bind使返回的对象包含每个参数的副本,包括函数对象将复制他们的论点.如果这些参数复制起来很昂贵,那么传递它们会很昂贵std::bind.

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

auto b = std::bind(func, arg1, arg2, arg3);
Run Code Online (Sandbox Code Playgroud)

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

auto b = std::make_tuple(func, arg1, arg2, arg3);
Run Code Online (Sandbox Code Playgroud)

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

auto b = std::bind(func, std::ref(arg1), arg2, arg3);
Run Code Online (Sandbox Code Playgroud)

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

b();  // equiv to std::get<0>(b)(std::get<1>(b), std::get<2>(b), std::get<3>(b))
Run Code Online (Sandbox Code Playgroud)

如果函数按值获取其参数,则绑定的参数将被复制到函数参数中.这可能很昂贵,但无论是直接调用函数还是在结果中调用它都是完全相同的std::bind......它是被调用函数的属性,而不是绑定表达式.

因此,使用的唯一开销boost::bind是在绑定参数的初始复制中,您可以通过移动参数来控制,以避免复制:

auto b = std::bind(func, std::move(arg1), arg2, arg3);
Run Code Online (Sandbox Code Playgroud)

或通过引用传递它们:

auto b = std::bind(func, std::ref(arg1), arg2, arg3);
Run Code Online (Sandbox Code Playgroud)

上面的讨论忽略了bind占位符和调用嵌套绑定表达式的功能,但这些不会影响性能,上面的所有内容仍然适用.

  • 我认为传递值的真正轻量级包装是`std :: cref`,而`std :: ref`应该保留给那些你真正需要可修改引用的情况? (2认同)