Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ : What are the purpose of captures in lambda expressions?

How are captures different than passing parameters into a lambda expression? When would I use a capture as opposed to just passing some variables?

for reference: http://en.cppreference.com/w/cpp/language/lambda#Lambda_capture

The reference only defines it as a "list of comma separated values" but not what they're for or why I'd use them.

To add: This is not the same question as "what is a lambda expression" because I'm not asking what a lambda expression is or when to use it. I'm asking what the purpose of a capture is. A capture is a component of a lambda expression, and can take values, but it's not well explained elsewhere on the internet what these values' intended purpose is, and how that is different from the passed values that follow the capture.

like image 747
dlo Avatar asked Oct 19 '25 10:10

dlo


2 Answers

A capture is a binding to a free variable in the lambda form. They turn the lambda expression into a closed form (a closure), with no free variables. Consider:

auto f1 = [](int a, int x, int y){ return a * x + y; };
int x = 40, y = 2;
auto f2 = [x, y](int a){ return a * x + y; };

Despite bodies being the same, in the second form x and y are free variables (they are not bound among function's arguments) and thus need to be bound to existing objects (i.e. captured) at the moment of form's instantiation. In the first form they are function arguments, as you first suggested, and thus need not to be bound to existing objects at the moment of form instantiation. The difference is obvious: f1 is the function of three arguments, while f2 only accepts one.

What is more important, captures hold the part of lambda's local context that can outlive the context itself. A simple example:

auto f(int x) {
    return [x](int a){ return a + x; };
}

Note that this function returns a fresh callable object, whose operator() accepts a single int and returns an int, and internally uses some value, a value of a variable that was local to the function f() and thus is no more accessible after the control has exited the function.

like image 126
bipll Avatar answered Oct 22 '25 01:10

bipll


You may want to pass your lambda to a function that calls it with a specific number of arguments (e.g., std::find_if passes a single argument to your function). Capturing variables permits you to effectively have more inputs (or outputs, if you capture by reference).

like image 30
Stephen Newell Avatar answered Oct 22 '25 01:10

Stephen Newell



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!