std :: bind在堆栈上?

问题描述

我想将 c ++ objcet成员回调func 传递给“ c” lib ,该文件仅具有void *。然后,我使用std :: function注册回调处理程序。但是当我将std :: function *转换为void *时出现问题,似乎std :: function *在转换为void *时被破坏了。

下面是测试代码

#include <iostream>
#include <functional>

class TfLight {
 public:
  void print(int a) {
    std::cout << "TfLight::print " << a << std::endl;
  }
};

class Server {
 public:
  void run(int a) {
    std::function<void(int)>* func = reinterpret_cast<std::function<void(int)>*>(ptr);
    std::cout << func << std::endl;
    (*func)(a);
  }
  
  void register(std::function<void(int)> tf) {
    std::cout << (&tf) << std::endl;
    // f = tf;
    setPtr(&tf);
  }
  
  void setPtr(void* p) {
    ptr = p;
  }
  
  std::function<void(int)> f;
  void* ptr;
};

int main()
{
    TfLight* tf = new TfLight();
    Server* server = new Server();
    server->register(std::bind(&TfLight::print,tf,std::placeholders::_1));
    server->run(3333);
    
    delete server;
    delete tf;
}

当我使用全局变量保存“ std :: function ”时,可以正常调用它。我该如何解决这个问题?

但是当我将std :: function *转换为void *时出现问题,似乎std :: function *在转换为void *时被破坏了

解决方法

std::bind是一个函数。它不在堆栈或堆中。

其返回值是一个临时对象,并且具有通常的临时寿命。这不是这里的问题。返回值bind存储在传递给std::function的{​​{1}}中。

register中,再次遵循常规的C ++规则。 register是一个函数参数,因此std::function<void(int)> tf)在调用期间一直有效。 &tf返回后,register便不复存在。注释掉的代码是正确的;您应该已经将其复制到tf

由于您拥有Server::f,因此Server::f似乎毫无意义。是的,您可以将void* Server::ptr设置为ptr,但是为什么呢?