The following is a stripped-down version of the problem:
#include <initializer_list>
#include <iostream>
enum objects { zero, one, two, three, four, five, six, seven };
std::initializer_list<objects> objects_list()
{
return { zero, one, two, three, four, five, six, seven };
}
int main()
{
for (auto a : objects_list())
{
std::cout << a << ' ';
}
std::cout << '\n';
}
My expectation is that the programs outputs:
0 1 2 3 4 5 6 7
which is comfirmed by GCC 4.9.2, but a GCC fresh from its git repository yields:
0 0 -85997960 32712 -1076836160 32765 0 32
which seem basically random numbers.
Is there a problem with my program or with GCC?
N4296 § 8.5.4/5 states
An object of type
std::initializer_list<E>
is constructed from an initializer list as if the implementation allocated a temporary array ofN
elements of typeconst E
, whereN
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 thestd::initializer_list<E>
object is constructed to refer to that array
So we're told that a std::initializer_list
refers to a temporary array.
and § 8.5.4/6 states
The array has the same lifetime as any other temporary object
And the standard provides this example to demonstrate that accessing an initializer list after its array has gone out of scope is undefined behavior:
struct A {
std::initializer_list<int> i4;
A() : i4{ 1, 2, 3 } {} // creates an A with a dangling reference
};
the
initializer_list
object is initialized in a constructor’s ctor-initializer, so the array persists only until the constructor exits, and so any use of the elements ofi4
after the constructor exits produces undefined behavior. —end example ]
You have a similar, but slightly different, example that involves copying:
std::initializer_list<objects> objects_list()
{
return { zero, one, two, three, four, five, six, seven };
}
By the logic from the standard, the array {zero, one, two, ...}
only persists for the duration of the objects_list
function.
18.9/2 [support.initlist] also supports that a copy will not persist the underlying array:
Copying an [
std::
]initializer list
does not copy the underlying elements.
So I believe your code is ultimately UB and the fact that it worked before was by luck.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With