【问题标题】:std::bind is on stack?std::bind 在堆栈上吗?
【发布时间】:2020-12-26 16:50:56
【问题描述】:

我想将 c++ objcet 成员回调函数 传递给一个 "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* 时被破坏了

【问题讨论】:

  • 旁白:您不需要new 来创建TfLight 或Server

标签: c++ stdbind


【解决方案1】:

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

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

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

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

【讨论】:

  • 谢谢你的回复!正如我之前所说,我需要使用 c lib。我通过类Server将c更改为c ++类对其进行了修改。我还需要将处理程序传递给c lib回调函数,它只有void *,所以我想试试这个。
  • 那么 std::function 就像其他临时对象一样,我需要持有它。有没有更优雅的方法来实现这一点?
  • @dahohu527:很可能最简单的解决方案是将整个Server* 作为void* 传递给您的C 回调。转换后,在回调中,您可以访问所有 Server 成员,包括任何存储的 std::function。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-23
  • 2016-05-20
  • 1970-01-01
  • 2023-04-01
  • 2011-08-01
  • 2012-12-13
相关资源
最近更新 更多