绑定功能时是否存在性能影响(正面或负面)(使用Boost Bind)?
答案 0 :(得分: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();
}
<强>更好;更喜欢这个:
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::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
,这是一种非常轻量级的类型,用于存储指向对象的指针: / 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
的功能,例如占位符和调用嵌套绑定表达式,但这些功能不会影响性能,上面的所有内容仍然适用。