Skip to content

Lambda functions

February 22, 2012

One of the biggest features added to C++ is the lambda function—unnamed functions written as an expression. One of their best uses is with the STL algorithms. Instead of having to write a class and instantiate it as a functor, you just write a lambda function right where you need to pass the functor to the algorithm.

When you write a lambda function, you are creating a function object, which when called with operator(), will call the body of the function that you just wrote. Additionally, you can bind local variables to the function object so that their value will be saved if you return the object out of the current function.

The syntax is:
[ capture-list ] ( parameter-list ) -> return_type { statements }

Here are a few broad ideas about lambda functions:

  • The return type can be auto if the body is simply return expr;
  • The parameter list is like any other parameter list, note that a lambda function can’t be templated.
  • You can capture any variable that is in scope by reference or value

The type of a lambda function is unspecified. To use a lambda function, you have to either use it where its type will be inferred by a template parameter, or assign it to a variable declared with auto. However, if the lambda function doesn’t capture any variables, its type shall be convertible to a function pointer with the same signature as the lambda function.

A lambda function can capture variables by either reference or by value. There are two ways to capture variables, explicitly or implicitly. To capture variables explicitly, include them in the capture list. If the variable is preceded by & then it is captured by reference, otherwise it is captured by value.

If the capture list starts with & or =—the default capture specifier—then all variables used in the lambda function’s body will be captured implicitly, by reference or by value respectively. The exception to that is if you explicitly list variables to be captured by the method other than the default. If the default capture is by reference, then no variable in the capture list can be preceded by a &, if the default is by value, then every variable listed must be preceded by a &.

Here are some examples:

void foo()
{
  int a, b, c;

  [&] {a = b + c;}; //everything is captured by reference
  [=, &b] {b = a + c;}; //only b is captured by reference
  [&a, b] {a = b + 1;}; //a is captured by reference, b by value

  std::vector<int> container;

  //initialise container with stuff

  //add up everything in the container
  std::for_each(container.begin(), container.end(),
    [&a] (int val) -> void
    {
      a += val;
    }
  );
}

Note that if you capture variables by reference, they must remain in scope as long as they are used by the lambda function. The results are undefined if a variable captured by reference goes out of scope before it is used.

Advertisements

From → Language

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: