From C++11 8.5.4 List Initialization [dcl.init.list]:
5 An object of type std::initializer_list<E>
is constructed from an initializer list as if the implementation allocated an array of N
elements of type E
, where N
is the number of elements in the initializer list. Each element of that array is copy-initialized with the corresponding element of the initializer list, and the std::initializer_list<E>
object is constructed to refer to that array. If a narrowing conversion is required to initialize any of the elements, the program is ill-formed.
6 The lifetime of the array is the same as that of the initializer_list
object.
The return
statement of your lambda initializes a temporary std::initializer_list<int>
and returns a copy thereof. This is all good, except that the lifetime of the array to which it refers ends at the end of the full-expression. Accessing the dead array through the initializer_list
outside of the lambda results in undefined behavior.
An initializer_list
isn't a container, it's a reference to a temporary container. If you try to use it like a container you're going to have a bad time.
In C++14 (quoting N4140) paragraph 6 was clarified to:
6 The array has the same lifetime as any other temporary object (12.2), except that initializing an initializer_list
object from the array extends the lifetime of the array exactly like binding a reference to a temporary.
by the resolution of CWG issue 1290. This clarification makes it impossible to use an initializer_list
as, e.g., a member variable which was the intention of C++11. Even in C++14, however, your program has undefined behavior.