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