此代码仅用于说明问题.
#include <functional>
struct MyCallBack {
void Fire() {
}
};
int main()
{
MyCallBack cb;
std::function<void(void)> func = std::bind(&MyCallBack::Fire, &cb);
}
Run Code Online (Sandbox Code Playgroud)
使用valgrind进行的实验表明,分配的行在funclinux上使用gcc 7.1.1动态分配大约24个字节.
在真正的代码中,我有一些不同的结构,所有结构都void(void)存储了大约1000万个成员函数 std::function<void(void)>.
在做std::function<void(void)> func = std::bind(&MyCallBack::Fire, &cb);什么时,有什么方法可以避免内存被动态分配?(或以其他方式将这些成员函数分配给a std::function)
Ser*_*eyA 20
不幸的是,分配器std::function已经被C++放弃了17.
现在,避免内部动态分配的公认解决方案std::function是使用lambdas而不是std::bind.这确实有效,至少在GCC中 - 它有足够的静态空间来存储lambda,但没有足够的空间来存储binder对象.
std::function<void()> func = [&cb]{ cb.Fire(); };
// sizeof lambda is sizeof(MyCallBack*), which is small enough
Run Code Online (Sandbox Code Playgroud)
作为一般规则,对于大多数实现,并且使用仅捕获单个指针(或引用)的lambda,您将std::function使用此技术避免内部动态分配(通常也是更好的方法,如其他答案所示).
请记住,为了工作,你需要保证这个lambda将比这更长寿std::function.显然,它并不总是可能的,有时你必须通过(大)副本捕获状态.如果出现这种情况,目前还没有办法消除功能动态分配,比用STL自己鼓捣其他(显然,不是一般情况下推荐,但在某些特定情况下可以做).
作为已经存在且正确答案的补充,请考虑以下事项:
MyCallBack cb;
std::cerr << sizeof(std::bind(&MyCallBack::Fire, &cb)) << "\n";
auto a = [&] { cb.Fire(); };
std::cerr << sizeof(a);
Run Code Online (Sandbox Code Playgroud)
这个程序为我打印24和8,包括gcc和clang.我不知道bind这里做了什么(我的理解是它是一个非常复杂的野兽),但正如你所看到的,与lambda相比,这里几乎是荒谬的低效率.
实际上,std::function如果从函数指针构造,则保证不分配,函数指针也是一个单词的大小.因此,std::function从这种lambda中构造一个只需要捕获指向对象的指针并且也应该是一个单词的lambda,实际上应该永远不会分配.