Lambda function capturing and memory usage

Discussion in 'C++' started by Juha Nieminen, Apr 22, 2012.

  1. I was wondering: Does memory usage increase every time that a lambda
    function captures variables, especially if it's then stored into a
    std::function wrapper?

    This question came up when I was thinking about a rather functional
    example usage of lambdas, like this:

    std::function<int(int)> multiplierFunction(int multiplier)
    {
    return [multiplier](int value) { return value * multiplier; };
    }

    The above function could be used eg. like:

    auto doubler = multiplierFunction(2);
    auto tripler = multiplierFunction(3);
    auto nMultiplier = multiplierFunction(n);

    std::cout << doubler(5) << " " << tripler(x) << " "
    << nMultiplier(y) << "\n";

    The values '2', '3' and 'n' have to be stored somewhere for (at least)
    as long as 'doubler', 'tripler' and 'nMultiplier' exist. Where are they
    stored and for how long? (Are they freed immediately when those variables
    go out of scope? How?)

    What worries me is the possible memory usage if the above function is
    used eg. in a loop, like:

    for(int i = 0; i < 1000000; ++i)
    {
    auto f = multiplierFunction(i);
    std::cout << f(2) << "\n";
    }

    Does memory usage increase a million-fold, or is the memory recycled after
    each loop?
    Juha Nieminen, Apr 22, 2012
    #1
    1. Advertising

  2. Juha Nieminen

    MelissA Guest

    On 22 Apr 2012 12:21:06 GMT
    Juha Nieminen <> wrote:

    >
    > for(int i = 0; i < 1000000; ++i)
    > {
    > auto f = multiplierFunction(i);
    > std::cout << f(2) << "\n";
    > }
    >
    > Does memory usage increase a million-fold, or is the memory recycled
    > after each loop?
    >
    >


    I have tested this code on Ubuntu 11.10 g++ 4.6.1 and memory does
    not increase.
    MelissA, Apr 22, 2012
    #2
    1. Advertising

  3. Juha Nieminen <> writes:

    > I was wondering: Does memory usage increase every time that a lambda
    > function captures variables, especially if it's then stored into a
    > std::function wrapper?


    Yes, some memory is used to keep the captures.

    > std::function<int(int)> multiplierFunction(int multiplier)
    > {
    > return [multiplier](int value) { return value * multiplier; };
    > }
    >
    > The above function could be used eg. like:
    >
    > auto doubler = multiplierFunction(2);
    > auto tripler = multiplierFunction(3);
    > auto nMultiplier = multiplierFunction(n);
    > std::cout << doubler(5) << " " << tripler(x) << " "
    > << nMultiplier(y) << "\n";
    >
    > The values '2', '3' and 'n' have to be stored somewhere for (at least)
    > as long as 'doubler', 'tripler' and 'nMultiplier' exist.


    You are absolutely right.

    > Where are they stored and for how long? (Are they freed immediately
    > when those variables go out of scope? How?)


    The code is generated once and for all (per template), and captured data
    is stored in an instance of a compiler-generated class. (At least,
    that's how I would implement it.)

    > What worries me is the possible memory usage if the above function is
    > used eg. in a loop, like:
    >
    > for(int i = 0; i < 1000000; ++i)
    > {
    > auto f = multiplierFunction(i);
    > std::cout << f(2) << "\n";
    > }
    >
    > Does memory usage increase a million-fold, or is the memory recycled after
    > each loop?


    The f object goes out of scope at each iteration, so there is no
    accumulation. If you were to place these functions inside an array, then
    it would probably fill up some memory...

    -- Alain.
    Alain Ketterlin, Apr 22, 2012
    #3
  4. Alain Ketterlin <-strasbg.fr> wrote:
    > The code is generated once and for all (per template), and captured data
    > is stored in an instance of a compiler-generated class. (At least,
    > that's how I would implement it.)


    I'm assuming that when you are using lambda functions directly, like

    auto func = [multiplier](int value) { return value * multiplier; };

    then the type of 'func' will be internally something very similar to a
    struct containing the value of 'multiplier' as a member, and the lambda
    operating on this "struct" exactly is if it were its member function.
    Thus, this "struct" is bound to the scope where it's created in the
    exact same way as any old-fashioned functor would be.

    *However*, std::function cannot have any such struct as a member.
    The type of eg. "std::function<int(int)>" never changes regardless of
    which kind of lambda is assigned to it, and how many variables might have
    been captured. (A clear sign of this is that you can use such
    std::function<int(int)> objects in non-templated code.) In this case the
    captured variables cannot be stored locally on the stack like they can
    when dealing with lambdas directly. They have to be stored somewhere else.

    Does std::function keep the "capture struct" on the heap? Does it manage
    it like a smart pointer would? Or does it do something even smarter?
    Juha Nieminen, Apr 22, 2012
    #4
  5. Juha Nieminen <> wrote:
    > Does std::function keep the "capture struct" on the heap? Does it manage
    > it like a smart pointer would? Or does it do something even smarter?


    So nobody knows the answer to this question?
    Juha Nieminen, Apr 24, 2012
    #5
  6. Juha Nieminen <> writes:

    > Juha Nieminen <> wrote:
    >> Does std::function keep the "capture struct" on the heap? Does it manage
    >> it like a smart pointer would? Or does it do something even smarter?


    That was my guess...

    > So nobody knows the answer to this question?


    I don't, but would appreciate any info on how this is implemented.

    -- Alain.
    Alain Ketterlin, Apr 24, 2012
    #6
  7. Juha Nieminen

    Guest

    On Tuesday, April 24, 2012 5:47:03 AM UTC-5, Juha Nieminen wrote:
    > Juha Nieminen <> wrote:
    > > Does std::function keep the "capture struct" on the heap? Does it manage
    > > it like a smart pointer would? Or does it do something even smarter?

    >
    > So nobody knows the answer to this question?


    std::function has to be polymorphic, so in general it needs to copy to the heap. The standard does not mandate that behavior, however, and even encourages implementors to optimize common cases (function pointer, member function pointer and object).
    , Apr 24, 2012
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Roman Suzi
    Replies:
    13
    Views:
    588
    Bengt Richter
    Jan 7, 2005
  2. Sohail Somani
    Replies:
    5
    Views:
    622
    Sohail Somani
    May 7, 2009
  3. Steve Dogers

    lambda vs non-lambda proc

    Steve Dogers, Mar 30, 2009, in forum: Ruby
    Replies:
    1
    Views:
    156
    Sean O'Halpin
    Mar 30, 2009
  4. Juha Nieminen
    Replies:
    1
    Views:
    429
    Juha Nieminen
    Apr 22, 2012
  5. Haochen Xie
    Replies:
    4
    Views:
    232
    Haochen Xie
    Mar 17, 2013
Loading...

Share This Page