簡體   English   中英

將成員函數綁定到局部靜態變量

[英]Binding member function to a local static variable

前提:

這是一個函數:

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

請參考我可能真正打算的新問題:
將成員函數綁定到成員變量

不,這不安全 (也無法按預期工作)。 靜態變量的所有實例所共享的A ,並綁定this在這個靜態函數對象kHandler調用時f1首次。 因此,bound參數始終等於您首先在其上調用f1的實例,即在您的情況下為a1

此功能基本上是相同的:

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

多次調用此函數,您將始終獲得第一個調用的值。 演示

備擇方案:

  • 但是,如果可以節省空間,則可以將成員變量用於綁定函數。 我想實現這一點很簡單。

  • 一種非線程安全的替代方法 (我建議您使用此方法!)可以將“ this”指針存儲在靜態成員變量(“ that”)中,並使f0靜態並使用“ that”代替“ this” :

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

Raymond Chen的評論是正確的-通過使用靜態,您只會創建一個kHandler實例,並且如果與該第一個調用關聯的A實例死亡,則綁定的“ this”指針將失效。

我建議刪除靜態:

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

   ::g(kHandler);
 }

這是安全的,因為在g調用的整個生命周期中都存在kHandler。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM