All about Lambda Expressions in C++ (Lambda vs Closure)

This article is organized as follows:-

  1. Definition of closure
  2. Why we came to Lambda Expressions?
  3. Lambda Expressions
    • Definition
    • Syntax
    • Example
    • Advantage
    • How lambda functions work internally
    • What is the type of lambda
    • Performance Evaluation
  4. A closer look at the definition of closure
  5. Difference between closure and lambda expressions

Definition of Closure:

To understand closures, we need to first understand about first class entities in a programming language.

For an object or function to be first-class, you should be able to

–create them,

–store them in data structures,

–pass them to a function as parameters,

–return them from a function and

–create copies of them.

Instances of classes are first-class objects in C++ but functions are not first-class entity in C++, before C++11.

Now, let us come to the concept of closures.

As per wikipedia definition, “In programming languages, a closure, also lexical closure or function closure, is a technique for implementing lexically scoped name binding in a language with first-class functions”.

what does it mean?

I’ll explain the whole concept of lambda expressions first and then come back to the explanation of each word of this definition.

Why we came to Lambda Expressions?

In C++ we use function pointers and function objects to achieve the role of first class functions.  i.e. to pass functions as arguments etc. Both these techniques have tradeoffs. Function pointers have minimal syntactic overhead but do not retain state within a scope, and function objects can maintain state but require the syntactic overhead of a class definition.

A lambda expression combines the benefits of function pointers and function objects and avoids their disadvantages. Like a function objects, a lambda is flexible and can maintain state (if you are confused about what maintaining state means, it is explained in a while, keep reading), but unlike a function object, its compact syntax doesn’t require an explicit class definition.

Lambda Expression Definition

  • Tool in C++ to create a closure.
  • A way of defining anonymous function object at the point where it is invoked or passed as an argument to function.
  • Similar to function without a function name.

Syntax

Picture1

The image is referenced from the Microsoft website.

  1. capture clause (Also known as the lambda-introducer in the C++ specification.)
  2. parameter list Optional. (Also known as the lambda declarator)
  3. mutable specification Optional.
  4. exception-specification Optional.
  5. Trailing-return-type Optional.
  6. lambda body.

Capture Clause

  • Specifies which variables from surrounding scope are captured
  • Specifies whether capture is by value or reference.
  • [] -> no variable access
  • [=] -> capture by value
  • [&] -> capture by reference

[ ] ( ) { }              no captures

[=] ( ) { }    captures everything by copy

[&] ( ) { }    captures everything by reference

[x] ( ) { }    captures x by copy

[&x] ( ) { }    captures x by reference

[&, x] ( ) { }    captures x by copy, everything else by reference

[=, &x] ( ) { }    captures x by reference, everything else by copy

Example

int main(){

int var1 = 3;
int var2 = 5;

// The following lambda expression captures var1 by value and
// var2 by reference.
auto f = [var1, &var] { return var1 + var2; };

var1 = 0;
var2 = 100;

// Call f and print its result.
cout << f() << endl;
}

Output:-

103

Parameter List

Same as parameter list of a function

Example

auto y = [] (int first, int second){

return first + second;

};

Mutable Keyword

  • Mutable keyword is used so that body of lambda expression can modify copies of external variables captured by value.
  • Following are 2 code snippets trying to do the same thing.

Picture2        Picture3

In code snippet 1, line- “cats = 8 ” is an error. To achieve this, we need to write ‘mutable’ as in code snippet 2.

Usage And Example

int main(){

// Create a list of integers with a few initial elements.

list<int> numbers;

numbers.push_back(13);

numbers.push_back(17);

// Use the find_if function and a lambda expression to find the

// first even number in the list.

const list<int>::const_iterator result =

find_if(numbers.begin(), numbers.end(),[](int n) { return (n % 2) == 0; });

// Print the result.

if (result != numbers.end()) {

cout << “The first even number in the list is ” << *result << “.” << endl;

} else {

cout << “The list contains no even numbers.” << endl;

}

}

Find_if function returns the first element in the list of numbers from begin to end which is even.

Here, we’ve used a lambda expression instead of using a function pointer to specify the constraint that element should be even because-

1.Body of the function was not reusable in the scope of our program

2.Defining  a function in such case will only add overhead.

3.The body was not too big.

4. The code has become more readable.

Major advantage of using lambdas- Maintaining state of functions: Avoid static variables

Consider the following code example-

Picture4

As can be seen, toMutate is a variable defined outside lambda1 but used/changed inside it, by making it mutable. Whenever lambda1 is called, toMutate is incremented. In this way we achieved the functionality of static variables, without actually using a static variable. This is what is called as maintaining state of  variable.

How Lambda functions work internally?

[&i] ( ) { std::cout << i; }

// is equivalent to

struct anonymous {

int &m_i;

anonymous(int &i) : m_i(i) {}

inline auto operator()()

{

std::cout << i;

}

};

  • The compiler generates unique anonymous class as above for each lambda function.
  • Capture list will become a constructor argument in closure, If you capture argument as value then corresponding type data member is created within the closure.
  • Moreover, you can declare variable/object in the lambda function argument, which will become an argument to call operator i.e. operator().

What is the type of lambda?

According to C++11 specifications,

“The type of the lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type — called the closure type.

The closure type for a lambda-expression has a public inline function call operator  whose parameters and return type are described by the lambda-expression’s parameter-declaration-clause and trailing-return-type respectively.”

As explained in the topic above, the code of lambda expression is converted by compiler into an anonymous class. This class is the type of lambda expression.

Performance evaluation:

Space Complexity:

Defining a lambda expression is basically defining a class. Space cost will be equivalent to a class that holds as many variables as captured by lambda clause.

The functor instance will be allocated space on the stack.

Time Complexity:

Time taken is equal to time required to create an object and call a function upon it.

Closures: A closer Look

Now, since we have learned everything about lambda expressions, let us come to the explanation of definition of closure-

As per wikipedia definition, “In programming languages, a closure, also lexical closure or function closure, is a technique for implementing lexically scoped name binding in a language with first-class functions”.

Lexically scoped means basically setting the scope of an entity from where it can be referenced. With lexical scoping, a name always refers to its lexical environment.

Name binding means association of data with identifiers.

For example, when we write int x; here int is the identifier and x is the data.

First class functions are already defined at the beginning.

So, closures are basically, a technique for associating data with identifiers and defining the scope of data, in a language with first class functions. As we read in the lambda function details above, lambda functions perform name binding, while maintaining the state of variables (it can use the variables defined in outer scope or it can create new variables in it’s own scope), and the lambda expression obtained is a first class entity.

What is the difference between lambda expression and closure?

According to Scott Meyers, the difference between lambda expression and a closure is the same as difference between a class and an instance of a class. Lambda expression is lie a class, i.e. it does not exist at runtime and closure is like an instance of class, that exists at runtime. The anonymous class generated by compiler when a lambda expression is defined, is called a closure.

 

 

 

 

Published by:

Neha Katyal

I am a research enthusiast, a software developer, a passionate writer and a seeker. From researching on various aspects of software design, to designing and developing 4G/5G algorithms, everything excites me. Besides my inclination towards software, I have a strong interest in spirituality. I am a seeker; learning yoga, meditation, aura cleansing, Vedic astrology, reading Vedic scriptures that can bring me closer to the ultimate truth, are a few things that has formed an integral part of my life. Apart from these, writing, reading fiction and sketching are the places where I find my home. I cannot just pass a bookstore, I cannot come out of a storm until I write a poem, I cannot admire an actor/actress until I sketch their portrait. Yes, I can be called as a 'multipotentialite'. I love to learn a lot, travel, imagine, read, write, draw, design, code, engage in dhyana and yog, serve others, spend time with family. Because, I feel, life is all about learning, falling, rising, feeling, enjoying every moment :-)

Categories Software DesignLeave a comment

Leave a comment