Lambda function capturing and memory usage

J

Juha Nieminen

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?
 
M

MelissA

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.
 
A

Alain Ketterlin

Juha Nieminen said:
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.
 
J

Juha Nieminen

Alain Ketterlin said:
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?
 
J

Juha Nieminen

Juha Nieminen said:
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?
 
C

cartec69

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).
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,983
Messages
2,570,187
Members
46,747
Latest member
jojoBizaroo

Latest Threads

Top