This code:
#include <iostream>
#include <string>
std::pair<std::initializer_list<std::string>, int> groups{ { "A", "B" }, 0 };
int main()
{
for (const auto& i : groups.first)
{
std::cout << i << '\n';
}
return 0;
}
compiles but returns segfault. Why?
Tested on gcc 8.3.0 and on online compilers.
I would just add a bit more details. An underlying array of
std::initializer_list
behaves kind-of similarly as temporaries. Consider the following class:and its usage in the following code:
It prints out
since at the first line, a temporary instance of type
X
is created (by converting constructor from1
) and destroyed as well. The reference stored intop
is then dangling.As for
std::initializer_list
, if you use it this way:then, the underlying (temporary) array exist as long as
l
exits. Therefore, the output is:However, if you switch to
The output is again
since the underlying (temporary) array exists only at the first line. Dereferencing the pointer to the elements of
l
then results in undefined behavior.Live demo is here.
std::initializer_list
is not meant to be stored, it is just meant for ... well initialization. Internally it just stores a pointer to the first element and the size. In your code thestd::string
objects are temporaries and theinitializer_list
neither takes ownership of them, neither extends their life, neither copies them (because it's not a container) so they go out of scope immediately after creation, but yourinitializer_list
still holds a pointer to them. That is why you get segmentation fault.For storing you should use a container, like
std::vector
orstd::array
.