C++提升绑定性能

C ++ Boost Bind Performance

本文关键字:性能 绑定 C++      更新时间:2023-10-16

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

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

std::bind(或boost::bind)的结果是一个所谓的"绑定表达式",它有一个un­知道&害羞;由实现确定的able类型。此类型是可调用,并且可以转换为in­3(或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();
}

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中传递它们,CCD_16是一种非常轻量级的类型,它存储指向对象的指针:

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

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

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