How are lambda captures initialized in case of nested lambdas?

First, note that whether a capture is by copy or by reference depends only on the lambda expression's own lambda-introducer (the initial [] part), per C++11 [expr.prim.lambda] paragraph 14 (or C++17 [expr.prim.lambda.capture] paragraph 10).

The pieces you quoted from C++11 [expr.prim.lambda]/16 (or the same in C++17 [expr.prim.lambda.capture]/13) change only what entity is captured, not the type of the capture. So in the example, the inner lambda used to initialize m2 captures the b from the original definition, by copy.

Then, note C++11 [expr.prim.lambda]/21:

When the lambda-expression is evaluated, the entities that are captured by copy are used to direct-initialize each corresponding non-static data member of the resulting closure object.

(C++17 [expr.prim.lambda.capture]/15 starts out the same, but additional wording is added for the init-capture syntax like [var=init].)

In the example, the inner lambda-expression for initializing m2 is evaluated, and the closure object's member for b is initialized, each time m1.operator() is invoked, not in the order the lambda-expression appears in the code. Since the lambda for m2 captures the original b by copy, it gets the value of that b at the time m1 is called. If m1 were called multiple times, that initial value for b could be different each time.


— if m1 captures the entity by reference, m2 captures the same entity captured by m1.

Yes, so b in m2's capture list captures not the reference itself (the capture of m1, that is), but the object that it points to.

But whether m2 captures b by value or by reference is determined solely by what's written in m2's capture list. There's no & before b, so b is captured by value.

when is b inside m2 initialised?

When control reaches auto m2 = ...;. At that point, the reference to b stored in m1 is examined, and the object it points to is copied into m2.


Here's an easier explanation.

  • When you capture a reference by value, you make a copy of the object that it points to.

  • When you capture a reference by reference, you make a reference to the object that it points to.

Here, "capturing a reference" applies equally well to capturing actual references, and to capturing reference-captures of enclosing lambdas.