Search code examples
c++lambdafunctor

Possible storage waste of storing lambda into std::function


The size of a lambda expression object with an empty capture-list is 1

But if you store it into std:function, its size becomes 48 (on my platform)

Imagine when you have a container that stores thousands of functions

The memory usage will be 48-times bigger if you store them into std::function

Even a lambda object capturing a small object (like an 8-sized pointer) is much smaller than a std::function

Do you have any better idea to save that unnecessary space-usage?


Solution

  • This is the price you pay for not needing to know the type of the function. All std::function<void()>s are interchangeable no matter which lambda they came from. If you want to store lots of the same type of function (with different captures) in a vector, you can make it a functor instead of a lambda (so that it has a name) and make a vector of that type.

    Example: With lambda:

    std::vector<std::function<void()>> funcs;
    for(int i = 0; i < 10000; i++)
        funcs.push_back([i]() {std::cout << i << std::endl;});
    for(auto& func : funcs)
        func();
    

    With functor:

    struct number_printing_function {
        int i;
        number_printing_function(int i) : i(i) {}
        void operator()() {
            std::cout << i << std::endl;
        }
    };
    
    std::vector<number_printing_function> funcs;
    for(int i = 0; i < 10000; i++)
        funcs.push_back(number_printing_function(i));
        // or funcs.emplace_back(i);
    
    for(auto& func : funcs)
        func();
    

    IMO this is a bit useless, because we might as well store a vector of ints and stop pretending they are functions. When you have many functors of the same type you already know what they do, so just do it. Really, the code above is just the code below, but with extra steps:

    std::vector<int> ints;
    for(int i = 0; i < 10000; i++)
        ints.push_back(i);
    for(auto& i : ints)
        std::cout << i << std::endl;