绑定成员函数到本地静态变量

时间:2014-10-24 02:34:28

标签: c++ static bind local

前提条件:

这是一个功能:

typedef std::function<void (int)> Handler;
void g(const Handler& h) {
  h(100);
}

,和一个班级:

class A {
 public:
  void f0(int n) {
    std::cout << m + n << std::endl;
  }

  void f1() {
    ::g(std::bind(&A::f0, this, std::placeholders::_1));
  }

  int m;
};

这将打印两行,'101'和'102':

int main() {
  A a1;
  a1.m = 1;
  a1.f1();

  A a2;
  a2.m = 2;
  a2.f1();

  return 0;
}

现在我意识到A::f1()将被频繁调用,
所以我修改了它(新版本):

  void A::f1() {
    static const Handler kHandler =
        std::bind(&A::f0, this, std::placeholders::_1);

    ::g(kHandler);
  }

我的问题:

this指针绑定到本地静态变量是否安全?

两个版本之间是否存在功能差异?

我可以期待新版本真正获得一些性能优势吗? (我怀疑我的编译器(MSVC)会自行优化它,
所以我可能不需要自己优化它。)

已编辑----------

我运行新版本并意识到结果与原始版本不同。
它再次打印两行“101”和“101”(不是“102”) 可怜的问题,对不起。

已编辑2 ----------

请参阅我可能真正想要的新问题:
Binding member function to a member variable

2 个答案:

答案 0 :(得分:1)

不,这不安全(也不按预期工作)。静态变量在A的所有实例之间共享,并且在第一次调用this时在此静态函数对象kHandler中绑定f1。因此,bound参数始终等于您首先调用f1的实例,即在您的情况下a1

这个功能基本相同:

int f(int a) {
    static int b = a;
    return b;
}

多次调用此函数,您将始终获得第一个调用的值。 (Demo

<强>备选方案:

  • 但是,如果您可以使用空间开销,则可以使用成员变量作为绑定函数。我想这是直截了当的。

  • 非线程安全的替代(我建议使用此!)可以存储&#34;此&# 34;指针在静态成员变量中(&#34;表示&#34;)并使f0静态并使用&#34;&#34;而不是&#34;这&#34;:

    class A {
        static A * that = nullptr;
    
    public:
        static void f0(int n) {
            assert(that);
            std::cout << that->m + n << std::endl;
        }
    
        void f1() {
            assert(!that);
            that = this;
            ::g(&A::f0);
            that = nullptr;
        }
    
        int m;
    };
    

答案 1 :(得分:0)

Raymond Chen的评论是正确的 - 通过使用静态你只创建了一个kHandler实例,如果与第一次调用关联的A实例死了,那么绑定的“this”指针就会死掉。

我建议删除静态:

void A::f1() {
   const Handler kHandler =
       std::bind(&A::f0, this, std::placeholders::_1);

   ::g(kHandler);
 }

这是安全的,因为kHandler将在g调用的整个生命周期中存在。