Emi*_*ier 22 c++ performance boost c++11 std-function
已经提出了C++"委托"的建议,其开销低于boost::function
:
是否已将这些想法用于实施std::function
,从而产生更好的性能boost::function
?有谁比较过std::function
vs 的表现boost::function
?
我想知道这个特别适用于英特尔64位架构上的GCC编译器和libstdc ++,但欢迎其他编译器的信息(例如Clang).
Jon*_*ely 28
在libstdc ++中,std::function
我们使用一个适当大小和对齐的联合类型来存储指针,函数指针或指向成员函数的指针.我们避免为可以存储在该大小和对齐中的任何函数对象进行堆分配,但仅限于它是"位置不变"的
/**
* Trait identifying "location-invariant" types, meaning that the
* address of the object (or any of its members) will not escape.
* Also implies a trivial copy constructor and assignment operator.
*/
Run Code Online (Sandbox Code Playgroud)
代码基于std::tr1::function
实现,该部分没有显着变化.我认为这可以简化使用,std::aligned_storage
并且可以通过专门化特性来改进,以便将更多类型识别为位置不变.
调用目标对象是在没有任何虚函数调用的情况下完成的,类型擦除是通过在std::function
函数模板特化的地址中存储单个函数指针来完成的.所有操作都是通过存储的指针调用该函数模板并传入一个枚举来识别它被要求执行的操作来完成的.这意味着没有vtable,只需要在对象中存储单个函数指针.
这个设计是由boost::function
原作者提供的,我相信它接近于提升实施.有关基本原理,请参阅Boost.Function 的Performance文档.这意味着GCC的std::function
速度不太快boost::function
,因为它是同一个人的类似设计.
注意我们std::function
不支持使用分配器构建,它需要做的任何分配都将使用new
.
为了回应Emile的评论,表达了避免堆分配的意图,该分配std::function
包含指向成员函数和对象的指针,这里有点破解(但你没有听到我的意思;-)
struct A {
int i = 0;
int foo() const { return 0; }
};
struct InvokeA
{
int operator()() const { return a->foo(); }
A* a;
};
namespace std
{
template<> struct __is_location_invariant<InvokeA>
{ static const bool value = true; };
}
int main()
{
A a;
InvokeA inv{ &a };
std::function<int()> f2(inv);
return f2();
}
Run Code Online (Sandbox Code Playgroud)
诀窍是它InvokeA
足够小以适应function
小的对象缓冲区,并且特征专门化说它可以安全地存储在那里,因此function
它直接保存该对象的副本,而不是堆上.a
只要指向它的指针仍然存在,这需要持久化,但如果function
目标是这样的话,情况就是如此bind(&A::foo, &a)
.