5

我目前正在研究网络软件。它有一个主类,server显然代表一个服务器实例。

实例可以server发送请求,并通过回调通知用户响应。

代码如下:

class server
{
  public:
    typedef boost::function<void (int duration)> callback_func;

    void send_request(endpoint& ep, callback_func cb);
};

现在假设,作为用户,我希望回调了解调用它的实例,我可以执行以下操作:

void mycallback(const server& sv, int duration) { ... }

server sv;
sv.send_request("localhost", boost::bind(&mycallback, boost::ref(sv), _1));

但我想知道:这样做有什么开销吗?通话mycallback会比使用“常规”通话慢吗?

谢谢你。

脚注:我当然可以将我的更改typedef为:typedef boost::function<void (const server& sv, int duration)> callback_func;如果boost::bind导致任何重大开销,那可能就是我最终会做的事情。我只想知道使用boost::bind.

4

4 回答 4

5

当然,它会导致开销。它的作用是创建一个函子,该函子存储绑定的参数并具有一个operator()您可以使用剩余参数调用的函子。现在,这很重要吗?我不知道,因为那只是一个词。发出 1000 万个请求并对其进行衡量。您是唯一可以判断此开销对您是否重要的​​人。

另外,我也遇到了类似的问题。因为我真的不需要委托,所以我可以摆脱函数指针。但我发现了一个有趣的基准,其中还提到了一些替代实现,它们的性能都比boost::function. 这是以可移植性为代价的,在某些情况下,实现中的丑陋、非标准的黑客攻击(但作为回报是非常好的性能)。

于 2011-05-05T08:55:25.667 回答
5

boost::bind生成一个函数对象,如果将其用作函数模板的参数,则可以对其进行优化,但会boost::function阻止此优化,就像将指针传递给函数将阻止其内联一样。boost::function本身不需要引入比虚函数 all 或通过函数指针调用更多的开销。

PS。我同意 Tamás Szelei 的观点:提出 1000 万个请求并对其进行衡量。

于 2011-05-05T09:01:55.357 回答
2

与普通函数调用相比,您需要为函数调用支付两次间接费用,这类似于(非去虚拟化)虚函数调用的开销。

第一个间接是由于 boost::function 中发生的类型擦除(这在文档中有boost::function记录)。这个不能真正优化,而且你也会用一个裸函数指针受到同样的惩罚。

第二种间接来自mycallback通过函数指针调用函数。一个非常优化的编译器可以解决这个问题并优化它,但一个普通的编译器不会。mycallback如果你变成一个函数对象,你可以摆脱这种间接(在所有编译器中) :

代替

void mycallback( .1. ) { .2. }

你做

struct mycallback {
    void operator()( .1. ) const { .2. }
};
于 2011-05-06T19:44:15.767 回答
1

请注意 boost::bind 会导致仿函数的副本。这可能非常重要。对于我的操作系统来说,新闻和删除非常昂贵。请参阅有关 ref() 和 cref() 的 boost::bind 文档。我相信成员函数也会导致仿函数副本,但没有关于此的文档。

于 2012-07-05T09:10:12.710 回答