Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do capture lists of lambdas actually work in C++11?

Tags:

c++

c++11

lambda

I know that capture lists make variables available inside a lambda function body like so:

int pos(0);
std::function<void()> incPos = [&pos](){ ++pos; };
incPos(); //pos is now 1

But how does that capturing actually work on compiler level? Where are the captured addresses or captured values stored?

like image 761
iFreilicht Avatar asked May 06 '14 16:05

iFreilicht


People also ask

How does lambda capture work?

By default, variables are captured by const value . This means when the lambda is created, the lambda captures a constant copy of the outer scope variable, which means that the lambda is not allowed to modify them. In the following example, we capture the variable ammo and try to decrement it.

What does it mean to lambda capture this?

A lambda is a syntax for creating a class. Capturing a variable means that variable is passed to the constructor for that class. A lambda can specify whether it's passed by reference or by value.

How do you capture a variable in lambda function?

Capturing Local Variables by value inside Lambda Function To capture the local variables by value, specify their name in capture list i.e. }; // Local Variables std::string msg = "Hello"; int counter = 10; // Defining Lambda function and // Capturing Local variables by Value auto func = [msg, counter] () { //... };

What is a lambda expression in C++11?

C++ Lambda expression allows us to define anonymous function objects (functors) which can either be used inline or passed as an argument. Lambda expression was introduced in C++11 for creating anonymous functors in a more convenient and concise way.


1 Answers

Each lambda expression generates a unique function object (closure) that stores the captured variables as data members. For instance, the lambda expression in your code would be transformed into something like this by the compiler:

struct __uniquely_named_lambda
{
  __uniquely_named_lambda(int& pos)
  : pos(pos) {}
  int& pos;

  void operator()() const
  { ++pos; }
};

Invoking the lambda is simply a call to operator().

The data member is a reference since you captured by reference. If you captured by value it would be a plain int. Also note that generated operator() is const by default. This is why you cannot modify captured variables unless you use the mutable keyword.

like image 152
Praetorian Avatar answered Sep 26 '22 14:09

Praetorian