dlo
dlo

Reputation: 83

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.

Upvotes: 4

Views: 3958

Answers (2)

bipll
bipll

Reputation: 11940

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.

Upvotes: 6

Stephen Newell
Stephen Newell

Reputation: 7828

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

Upvotes: 3

Related Questions