Building an initializer_list by listing values ​​contains random values

Thinking about the solution of std :: initializer list from an existing std :: array without listing each element , I developed a similar mechanism like bolov , but did not create an object, but rather just a list of initializers. I was surprised that my solution did not work, and I could not understand why.

#include <initializer_list> #include <iostream> #include <array> template<typename T, std::size_t N, std::size_t... Is> std::initializer_list<T> array_to_init_list_helper(std::array<T, N> arr, std::index_sequence<Is...>) { return {arr[Is]...}; } template<typename T, std::size_t N> std::initializer_list<T> array_to_init_list(std::array<T, N> arr) { return array_to_init_list_helper(arr, std::make_index_sequence<N>{}); } int main() { std::array<int, 5> arr{1, 2, 3, 4, 5}; auto init_list = array_to_init_list(arr); for (auto val : init_list) std::cout << val << " "; } 

I am getting random values while I would expect to get arr values.

+7
c ++ c ++ 11 initializer-list
source share
2 answers

Going through the assembly here (clang 4.0.0) and / or here (GCC 7.1), it is clear that std::initializer_list uses a dangling pointer, which (as we all know) produces seemingly random output.

EDIT

This result, of course, matches the comment made by Igor Tandetnik , citing cppreference.com :

A basic array is a temporary array of type const T [N], in which each element is initialized with a copy (except that narrowing conversions is invalid) from the corresponding element in the initial list of initializers. The lifetime of the base array is the same as any other temporary object, except that initializing the initializer_list object from the array extends the lifetime of the array in the same way as linking to a temporary one (with the same exceptions, for example, to initialize a non- -static class member ) The base array can be allocated in read-only memory.

+1
source share

[dcl.init.list] / 5 An object of type std::initializer_list<E> constructed from a list of initializers, as if the implementation allocated an array of elements N type E , where N is the number of elements in the list of initializers. Each element of this array is initialized with a copy with the corresponding element of the list of initializers, and the std::initializer_list<E> object is created to access this array.

[dcl.init.list] / 6 The lifetime of the array is the same as the initializer_list object.

This last part is important for your example. array_to_init_list_helper returns a copy of the original initializer_list , but the lifetime of the base array ends with an instance of the original. A copy refers to an item whose life has already expired. Then your program demonstrates undefined behavior.

+1
source share

All Articles