std::bind 在堆栈上?

dah*_*527 0 c++ stdbind

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

下面是测试代码。

#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;
}
Run Code Online (Sandbox Code Playgroud)

当我使用全局变量来持有“std::function<void(int)>”时,它可以正常调用。我该如何处理这个问题?

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

MSa*_*ers 7

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

它的返回值是一个临时对象,并且具有通常的临时对象生命周期。这不是这里的问题;在bind返回值存储在std::function传递给register

在 中register,再次遵循正常的 C++ 规则。std::function<void(int)> tf)是一个函数参数,因此&tf在调用期间保持有效。一register回来,tf就不复存在了。注释掉的代码是正确的;你应该把它复制到Server::f.

既然你有Server::f,这void* Server::ptr似乎完全没有意义。是的,您可以设置ptr&f,但为什么呢?

  • @dahohu527:最简单的解决方案很可能是将整个 `Server*` 作为 `void*` 传递给您的 C 回调。强制转换后,在回调内,您可以访问所有“Server”成员,包括任何存储的“std::function”。 (2认同)