Many topics told us that use small object like lambda expression could avoid heap allocation when using std::function
. But my study shows not that way.
This is my experiment code, very simple
#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;
}
And I compile it on centos7, with gcc version 4.8.5 20150623 But the valgrind shows this:
==22903== HEAP SUMMARY:
==22903== in use at exit: 0 bytes in 0 blocks
==22903== total heap usage: 1 allocs, 1 frees, 8 bytes allocated
Even if I remove the reference capture, just a plain lambda function. It still cost 1 byte heap allocation.
Is there somthing wrong of me to get small object optimization.
Update:
Thanks for the repies. I think I should add more detail of my experiment.
In order to eliminate the possible cause of refrence capturing. I removed capture, code like this:
FUNC_PROTO functor = [](int a, int b) {return a + b; };
Valgrind shows this:
==16691== total heap usage: 1 allocs, 1 frees, 1 bytes allocated
Still 1 byte heap allocation.
I also tried this to eliminate possible influence of lambda itself(which I think not)
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;
}
}
Valgrind shows:
==17414== total heap usage: 12 allocs, 12 frees, 12 bytes allocated
That could prove that the functors are not fully stack based object.
And this is my build script:
g++ test.cpp -o test -std=c++11 -g -O3 -DNDEBUG
This is my valgrind script:
valgrind --log-file=valgrind.log --tool=memcheck --leak-check=full --show-leak-kinds=all ./test
cout <<
. – Harmonious-O2
/-O3
? – Belovostd::function
applies type erasure, which, generally, needs to allocate. Though it can also employ some form of small buffer/object optimization technique. Note that your lambda capturestest
, therefore, it has subobjects. BTW, what is your compiler? – Bonefishcout << Test{}.Add(1, 2) << endl;
? On my system I have 2 allocations with and without usingstd::function
. – Prairie