Ker*_* SB 11
也许,可能不是.这取决于.
std::bind(或者boost::bind)的结果是所谓的"绑定表达",其具有由实现确定的不可知类型.此类型是Callable,可以转换为std::function(或boost::function)实例.
在内部,function(可能)使用类型擦除来处理各种复杂的,有状态的"可调用对象".这需要在一些(但不一定是所有)情况下进行动态分配和虚拟调度.这两个bind和function是有状态的,因为它们存储绑定参数.
结果是你应该尽可能避免将绑定表达式转换为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)
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占位符和调用嵌套绑定表达式的功能,但这些不会影响性能,上面的所有内容仍然适用.