Consider the following program:

#include <iostream> int f(int i) { std::cout << i; return i; } int main() { [a=f(1), b=f(2)]{}(); }

It prints 12 (with all major c++ compilers). That means, that the function call f(1) is executed before f(2). My question simply is: Is this order guaranteed by the C++ standard?


There is this question, which goes into a similar direction. The OP of that question just assumes:

we have no guarantee about the order for a list of lambda-capture initializers

The answer is oriented about a workaround and does not give an answer to my question.

Jakob Stark's user avatar

8

Is this order guaranteed by the C++ standard?

No, the order is unspecified. This is because as per expr.prim.lambda.capture#15 the initializations of the non-static data members corresponding to the captures(by copy) is explicitly left unspecified:

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, and the non-static data members corresponding to the init-captures are initialized as indicated by the corresponding initializer (which may be copy- or direct-initialization). (For array members, the array elements are direct-initialized in increasing subscript order.) These initializations are performed in the (unspecified) order in which the non-static data members are declared.


Note that this is a consequence of the fact that the order in which the non-static members corresponding to the capture(s) are declared, is itself unspecified as per expr.prim.lambda.capture#10:

For each entity captured by copy, an unnamed non-static data member is declared in the closure type. The declaration order of these members is unspecified. The type of such a data member is the referenced type if the entity is a reference to an object, an lvalue reference to the referenced function type if the entity is a reference to a function, or the type of the corresponding captured entity otherwise. A member of an anonymous union shall not be captured by copy.

This means that the implementations are allowed to use any order they see fit and they're not required to document that behavior. See Unspecified and implementation-defined behavior.


Also note that there is a proposal P3847R0 that aims to fix the ordering to be left-to-right.

Richard's user avatar

2 Comments

I can at least see a use for leaving the order unspecified, would allow for possible packing of capturespures. Although there are also possible benefits of having it be specified (able to use an already-captured value as part of a later initializer, trade-offs either way.

2026-01-28T18:14:43.137Z+00:00

Yes, though I think just like in order is now fixed in an initializer list { }, it would only make the language more consistent(no surprise to users relying on order) if captures of lambda also had fixed order.

2026-01-29T02:10:42.757Z+00:00

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.