结合成员函数局部静态变量(Binding member function to a local st

2019-10-21 04:19发布

前提:

这里是一个函数:

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)会自行优化它,
所以我可能不需要由我自己来优化它)。

EDITED ----------

我运行的新版本,实现的结果是不一样的原始之一。
它再次打印两行,“101”和“101”(不是“102”)。
可怜的问题,对不起所有。

组织编写----------

请参考我的新的问题,我可能真的打算:
结合成员函数的成员变量

Answer 1:

Raymond Chen的评论是正确的 - 通过使用静态你永远只能创建kHandler的一个实例,如果A的这种初次通话相关的实例会消逝,那么势必“this”指针会死人的。

我建议删除静态:

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

   ::g(kHandler);
 }

这是安全的,因为kHandler将整个摹通话的寿命存在。



Answer 2:

不,这不是安全的 (也按预期工作)。 静态变量的所有实例所共享的A ,并绑定this在这个静态函数对象kHandler调用时f1首次。 所以绑定参数总是等于在其上调用的类实例f1在你的情况先,即a1

它基本上与此功能是相同的:

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

调用这个函数多次,你总是会得到的第一个电话的价值。 ( 演示 )

备择方案:

  • 你可以,如果你可以用一个空间开销住,用一个成员变量绑定功能,虽然。 我估计,实施这个是直截了当的。

  • 非线程安全的替代品 (我建议使用此!)可能是对“this”指针存储在静态成员变量(“说”),使f0的静态和使用的“认为”,而不是“本” :

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


文章来源: Binding member function to a local static variable