避免使用 std::function 和成员函数分配内存

新手上路,请多包涵

此代码仅用于说明问题。

 #include <functional>
struct MyCallBack {
    void Fire() {
    }
};

int main()
{
    MyCallBack cb;
    std::function<void(void)> func = std::bind(&MyCallBack::Fire, &cb);
}

valgrind 的实验表明,分配给 func 的行在 linux 上使用 gcc 7.1.1 动态分配了大约 24 个字节。

在实际代码中,我有几个不同的结构,它们都有一个 void(void) 成员函数,存储在大约 1000 万个 std::function<void(void)> 中。

有什么办法可以避免在执行 std::function<void(void)> func = std::bind(&MyCallBack::Fire, &cb); 时动态分配内存? (或以其他方式将这些成员函数分配给 std::function

原文由 binary01 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 945
1 个回答

不幸的是,用于 std::function 的分配器已在 C++17 中删除。

现在,避免在 std::function 内进行动态分配的公认解决方案是使用 lambdas 而不是 std::bind 。这确实有效,至少在 GCC 中 - 它有足够的静态空间来存储您的情况下的 lambda,但没有足够的空间来存储活页夹对象。

 std::function<void()> func = [&cb]{ cb.Fire(); };
    // sizeof lambda is sizeof(MyCallBack*), which is small enough

作为一般规则,对于大多数实现,并且使用仅捕获单个指针(或引用)的 lambda,您将避免使用这种技术在 std::function 内进行动态分配(它通常也比其他方法更好答案建议)。

请记住,要使其正常工作,您需要保证此 lambda 的寿命会超过 std::function 。显然,这并不总是可能的,有时您必须通过(大)副本来捕获状态。如果发生这种情况,目前没有办法消除函数中的动态分配,除了自己修补 STL(显然,在一般情况下不推荐,但在某些特定情况下可以这样做)。

原文由 SergeyA 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题