前提条件:
这是一个功能:
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
答案 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调用的整个生命周期中存在。