wen*_*ndi 6 c++ c++11 std-function
许多主题告诉我们,使用像 lambda 表达式这样的小对象可以避免在使用std::function. 但我的研究表明并非如此。
这是我的实验代码,很简单
#include <iostream>
#include <functional>
using namespace std;
typedef std::function<int(int, int)> FUNC_PROTO;
class Test
{
public:
int Add(int x, int y) { return x + y; }
};
int main()
{
Test test;
FUNC_PROTO functor = [&test](int a, int b) {return test.Add(a, b); };
cout << functor(1, 2) << endl;
}
Run Code Online (Sandbox Code Playgroud)
我在centos7上编译它,gcc版本4.8.5 20150623但是valgrind显示了这一点:
==22903== HEAP SUMMARY:
==22903== in use at exit: 0 bytes in 0 blocks
==22903== total heap usage: 1 allocs, 1 frees, 8 bytes allocated
Run Code Online (Sandbox Code Playgroud)
即使我删除了引用捕获,也只是一个普通的 lambda 函数。它仍然花费 1 字节堆分配。
我进行小对象优化有什么问题吗?
更新:
感谢您的回复。我想我应该添加更多实验细节。
以排除可能导致参考捕获的原因。我删除了捕获,代码如下:
FUNC_PROTO functor = [](int a, int b) {return a + b; };
Run Code Online (Sandbox Code Playgroud)
Valgrind 展示了这一点:
==16691== total heap usage: 1 allocs, 1 frees, 1 bytes allocated
Run Code Online (Sandbox Code Playgroud)
仍然是 1 字节堆分配。
我也尝试过这样做来消除 lambda 本身可能的影响(我认为不是)
FUNC_PROTO functor = [](int a, int b) {return a + b; };
FUNC_PROTO functor2 = [](int a, int b) {return a * b; };
FUNC_PROTO test = nullptr;
for ( int i = 0; i < 10; ++i)
{
if (i % 2 == 0)
{
test = functor;
}
else
{
test = functor2;
}
}
Run Code Online (Sandbox Code Playgroud)
Valgrind 显示:
==17414== total heap usage: 12 allocs, 12 frees, 12 bytes allocated
Run Code Online (Sandbox Code Playgroud)
这可以证明函子不是完全基于堆栈的对象。
这是我的构建脚本:
g++ test.cpp -o test -std=c++11 -g -O3 -DNDEBUG
Run Code Online (Sandbox Code Playgroud)
这是我的 valgrind 脚本:
valgrind --log-file=valgrind.log --tool=memcheck --leak-check=full --show-leak-kinds=all ./test
Run Code Online (Sandbox Code Playgroud)
旧版本的 libstdc++,例如 gcc 4.8.5 附带的版本,似乎只优化函数指针而不进行分配(如此处所示)。
由于该std::function实现没有您想要的小对象优化,因此您将不得不使用替代实现。要么升级你的编译器,要么使用boost::function,这与std::function.