小对象优化在使用 std::function 中无用

small object optimization useless in using std::function

很多话题都告诉我们在使用std::function时使用像lambda表达式这样的小​​对象可以避免堆分配。但我的研究表明并非如此。

这是我的实验代码,很简单

#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;
}

我是在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

即使我删除了引用捕获,也只是一个普通的 lambda 函数。它仍然需要 1 字节的堆分配。

我做小对象优化有什么问题吗

更新:

感谢您的回复。我想我应该添加更多实验细节。

为了排除引用捕获的可能原因。我删除了捕获,代码如下:

FUNC_PROTO functor = [](int a, int b) {return a + b; };

Valgrind 显示:

==16691==   total heap usage: 1 allocs, 1 frees, 1 bytes allocated

还有 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;
    }
}

Valgrind 显示:

==17414==   total heap usage: 12 allocs, 12 frees, 12 bytes allocated

这可以证明仿函数不是完全基于堆栈的对象。

这是我的构建脚本:

g++ test.cpp -o test  -std=c++11 -g -O3 -DNDEBUG

这是我的 valgrind 脚本:

valgrind --log-file=valgrind.log --tool=memcheck --leak-check=full --show-leak-kinds=all ./test

旧版本的 libstdc++,例如 gcc 4.8.5 发布的版本,似乎只优化函数指针而不分配(如 here 所示)。

由于 std::function 实现没有您想要的小对象优化,您将不得不使用替代实现。升级您的编译器或使用 boost::function,这与 std::function.

基本相同