C++ 将成员函数绑定到局部静态变量
前提条件: 以下是一个函数:C++ 将成员函数绑定到局部静态变量,c++,static,bind,local,C++,Static,Bind,Local,前提条件: 以下是一个函数: typedef std::function<void (int)> Handler; void g(const Handler& h) { h(100); } int f(int a) { static int b = a; return b; } 现在我意识到A::f1()将被频繁调用, 因此,我对其进行了如下修改(新版本): 我的问题: 将此指针绑定到本地静态变量安全吗? 两个版本之间是否没有功能差异? 我能指望新版本
typedef std::function<void (int)> Handler;
void g(const Handler& h) {
h(100);
}
int f(int a) {
static int b = a;
return b;
}
现在我意识到A::f1()
将被频繁调用,因此,我对其进行了如下修改(新版本): 我的问题: 将
此指针绑定到本地静态变量安全吗?
两个版本之间是否没有功能差异?
我能指望新版本真的会获得一些性能优势吗?
(我怀疑我的编译器(MSVC)会自行优化它,
因此,我可能不需要自己对其进行优化)。
编辑------------
我运行了新版本,发现结果与原来的不一样。
它再次打印两行“101”和“101”(不是“102”)。
可怜的问题,对不起
已编辑2------
请参考我真正想问的新问题:
不,这不安全(也不能按预期工作)。静态变量在所有实例中共享到A
,当第一次调用f1
时,您可以将this
绑定到此静态函数对象kHandler
。因此,绑定参数始终等于您首先调用的f1
实例,即在您的情况下a1
这个功能基本上是一样的:
typedef std::function<void (int)> Handler;
void g(const Handler& h) {
h(100);
}
int f(int a) {
static int b = a;
return b;
}
多次调用此函数,您将始终获得第一次调用的值。()
备选方案:
- 但是,如果您能够承受空间开销,那么可以为绑定函数使用成员变量。我想实现这一点很简单
- 非线程安全的替代方法(我不建议使用它!)可以是将“this”指针存储在静态成员变量(“that”)中,并使
f0
为静态,并使用“that”而不是“this”:
A类{
静态A*表示为空ptr;
公众:
静态无效f0(整数n){
断言;
std::cout m+nRaymond Chen的评论是正确的-通过使用static,您只创建了一个kHandler实例,如果与第一个调用相关联的实例已死亡,则绑定的“this”指针将死亡
我建议删除静态:
void A::f1() {
const Handler kHandler =
std::bind(&A::f0, this, std::placeholders::_1);
::g(kHandler);
}
这是安全的,因为kHandler将在g调用的整个生命周期内存在。如果为不同的实例调用A::f1
,这是危险的,因为第一个实例将在静态中捕获,而所有其他实例将使用绑定到第一个实例(可能不再存在)的副本@RaymondChen:你说得对。我运行了这段代码并解决了这个问题。我刚刚意识到这正是你的示例代码中发生的情况,因此如果你真的尝试过,你会注意到这个问题。嗯,这与原始代码(在优化方法之前)没有任何优势@leemes:我同意你的看法,但我只是想知道一个成员函数是否可以绑定到一个局部静态变量,我意识到它不能。无论如何,也谢谢你的回答。(*)
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;
};
void A::f1() {
const Handler kHandler =
std::bind(&A::f0, this, std::placeholders::_1);
::g(kHandler);
}