22

已经有关于 C++“委托”的提议,其开销低于boost::function

有没有使用这些想法来实现std::function,从而产生比 更好的性能boost::function?有没有人比较过std::functionvs的表现boost::function

我想专门针对英特尔 64 位架构上的 GCC 编译器和 libstdc++ 了解这一点,但欢迎提供有关其他编译器的信息(例如 Clang)。

4

2 回答 2

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.
 */

该代码基于std::tr1::function实现,该部分没有显着变化。我认为这可以简化使用std::aligned_storage并且可以通过专门化特征来改进,以便将更多类型识别为位置不变。

调用目标对象是在没有任何虚函数调用的情况下完成的,类型擦除是通过在其中存储一个函数指针来完成的,该指针std::function是函数模板特化的地址。所有操作都是通过存储的指针调用该函数模板并传入一个枚举来确定它被要求执行的操作。这意味着不需要 vtable,并且只需要在对象中存储一个函数指针。

这个设计是由boost::function原作者贡献的,我相信它接近于 boost 的实现。有关基本原理,请参阅 Boost.Function 的性能文档。这意味着 GCC 不太可能std::function比 更快boost::function,因为它是同一个人的类似设计。

注意,我们std::function还不支持使用分配器进行构造,它需要做的任何分配都将使用new.


为了回应 Emile 的评论,该评论表示希望避免为std::function包含指向成员函数和对象的指针的 a 进行堆分配,这里有一个小技巧(但你没有从我这里听到 ;-)

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();
}

诀窍是它InvokeA足够小以适合function的小对象缓冲区,并且 trait 特化表示存储在那里是安全的,因此function直接保存该对象的副本,而不是在堆上。a只要指向它的指针持续存在,这就需要持续存在,但是如果function' 的目标是bind(&A::foo, &a).

于 2012-06-20T20:34:32.587 回答
4

正如评论中所指出的,std::function 只是一个接口,不同的实现可能会做不同的事情,但值得注意的是,标准确实对此事有话要说。从 20.8.11.2.1/5 (看起来更像是一个 IP 地址而不是标准的一部分):

注意:鼓励实现避免为小的可调用对象使用动态分配的内存,例如,其中 f 的目标是一个只包含一个指针或对一个对象的引用和一个成员函数指针的对象。——尾注

This is the standard's way of encouraging implementers to employ the "small function optimization," which was motivated by the cited articles on delegates. (The articles themselves don't actually talk about delegates in the .NET sense. Rather, they use the term "delegate" to mean bound member functions.)

于 2012-10-21T16:59:18.840 回答