[英]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.