【问题标题】:lightweight boost::bind轻量级 boost::bind
【发布时间】:2008-12-19 15:49:51
【问题描述】:

我非常讨厌 pass-callback-data-as-void*-struct 反模式。 Boost bind 很好地解决了它,但它是一个不可接受的依赖项。什么是轻量级的替代品?我如何尽可能简单地自己编写它?

【问题讨论】:

  • 您能否举例说明您是如何使用 boost::bind 的,以便我们可以看到您试图解决的低效率问题?
  • Boost bind 在我遇到的这个词的任何定义中都不是“重”。你能解释一下你的意思吗?
  • @Marcin,对于某些每微秒都很重要的领域来说,这绝对是太重了。特别是在您必须将生成的闭包传递到其创建上下文之外并且编译器在调用时无法对其进行优化的情况。

标签: c++ function boost binders


【解决方案1】:

首先,我质疑你的说法,即它对你来说太重了。

其次,滚动你自己的模板,如果你需要控制行为。

第三,如果您害怕滚动自己的模板,我怀疑您判断boost::bind 太重而无法使用的能力。

【讨论】:

  • 我同意,尤其是当您考虑编译器优化时。这些将减轻 boost::bind 的大部分感知“重量”。
  • @Brian 取决于上下文。在调用站点与构建站点不同的情况下,编译器将无法优化其中的大部分。事实上,您可能会将其存储在 boost::function 中,这会增加开销。
【解决方案2】:

查看 Don Clugston 的 fast delegate。它应该是您在大多数当前平台上可以找到的最快的委托(编译成 2 条汇编指令。) 1.4+ 版获得了一些 Boost.Bind 兼容性。

【讨论】:

    【解决方案3】:

    我不熟悉 boost:bind,但它是这样的吗?

    #include <iostream>
    
    void foo (int const& x) {
        std::cout << "x = " << x << std::endl;
    }
    
    void bar (std::string const& s) {
        std::cout << "s = " << s << std::endl;
    }
    
    template<class T>
    void relay (void (*f)(T const&), T const& a) {
        f(a);
    }
    
    int main (int argc, char *argv[])
    {
        std::string msg("Hello World!");
        relay (foo, 1138);
        relay (bar, msg);
    }
    

    输出——

    x = 1138
    s = Hello World!
    

    【讨论】:

    • 不完全。如果relay() 返回一个具有operator() 的对象,然后调用它调用foo(1138) 或bar(msg),那么你会更接近Boost.Bind。你所做的只是一个简单的回调机制。
    • 这就是我需要的全部开始,我可以自己完成仿函数部分。
    【解决方案4】:

    当与 boost::bind 一起使用时,Boost.Function 在 1.34 左右显着提高了性能。如果您使用旧的 bo​​ost 版本进行了配置,则可以使用更新的版本再次进行配置。 boost::function 能够将小函数对象保存在分配在堆栈上的小缓冲区中,而不是在堆上(使用放置新)。

    查看此邮件列表消息:http://lists.boost.org/Archives/boost/2006/01/98993.php

    【讨论】:

      【解决方案5】:

      一个常见的 C++ 习惯用法是使用函子(即覆盖 operator() 的对象)。关键是您使用单个对象来封装要回调的代码以及该代码将作用于的数据。仿函数是手动滚动的,还是使用 boost::bind 和/或 生成的,可能不会对运行时开销产生很大影响。

      所以而不是:

      typedef void (*cb)(void*);
      void funcThatNeedsCallback(cb thecallback, void *thedata) {
          // blah blah
          thecallback(thedata);
      }
      

      做:

      template<typename T>
      void funcThatNeedsCallback(T &thefunctor) {
          // blah blah
          thefunctor();
      }
      

      然后调用者这样做:

      struct MyFunctor {
          int mydata1;
          char *mydata2;
          void operator()(void) {
              // do something with mydata1 and mydata2
          }
      };
      
      MyFunctor mf = { value1, value2 };
      funcThatNeedsCallback(mf);
      

      显然,如果您愿意,可以将成员设为私有并将它们传递给构造函数,而不是使用初始化列表。

      如果您担心模板(例如,如果 funcThatNeedsCallback 是很多重复的代码),那么使用抽象类来定义参数必须具有的虚拟方法,并将该方法用作回调:

      class CallbackInterface {
          virtual void theCallback(void) = 0;
          virtual ~CallbackInterface() {} // just in case
      };
      
      void funcThatNeedsCallback(CallbackInterface &cb) {
          // blah blah
          cb.theCallback();
      }
      

      【讨论】:

        【解决方案6】:

        libsigc++。许可证是 LGPL,但实现是关于 Boost.Signal 的作用(我正在阅读“太重量级”的意思是“安装所有 Boost 太重量级”而不是“Boost.Signal 太慢”)。

        【讨论】:

        • 这看起来真的很有用。但是,通过“重量级”,我认为原始发布者意味着 CPU 时间。 libsigc++ 运行得更快吗?
        • @Vortico:老实说,我不知道任何一个库的运行速度是否明显快于另一个。我记得几年前当我查看实现时,库的内部结构非常相似,所以如果存在性能差异,我会感到惊讶。我可以说我从来没有注意到单击 UI 元素和使用任一库获得响应之间的停顿;所以(对我来说)它们都“足够快”。
        • 虽然我的实现几乎可以肯定与其他实现不同,但我发现 libsigc++ 在重复调用回调函数时比 Boost 绑定/函数慢 10 倍左右。 (我需要每秒调用大约 1 亿次回调,所以我可能应该重新设计以调用原始指针。)
        • @Vortico:您甚至可以避免函数指针的开销(hpl.hp.com/techreports/92/HPL-92-65.html):“[U]sing [functors] 不仅避免了间接函数调用的开销(如在传递指向函数的指针时发生),它甚至消除了直接调用的成本”(第 7 页)。就编译器的优化器而言,我怀疑 lambda 具有相同的属性。但是,由于我不必担心这种水平的表现,我可能不是接受建议的合适人选。
        【解决方案7】:

        捍卫 boost::binds 速度的人们可能从未编写过低延迟交易系统或高速图形库。
        Boost 是一个很好的通用库,而不是速度优化的库。相比之下,一些 boost 库(与调整后的实现相比)可能相当慢。

        对于函数/委托,请参阅http://www.codeproject.com/KB/cpp/fastdelegate2.aspx 以获得有用的比较。

        Ciao.

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-04-07
          • 2011-07-11
          • 2013-07-09
          • 2012-09-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多