通过枚举值构造initializer_list包含随机值

时间:2017-08-07 13:05:52

标签: c++ c++11 initializer-list

在考虑问题std::initializer list from already existing std::array without enumerating each element的解决方案时,我开发了与bolov类似的机制,但没有构建对象,而只是初始化列表。我很惊讶我的解决方案不起作用,我无法弄清楚原因。

#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 << " ";
}

我是getting random values,而我希望获得arr的值。

2 个答案:

答案 0 :(得分:1)

通过程序集here(clang 4.0.0)和/或here(GCC 7.1),显然std::initializer_list正在使用悬空指针,我们都知道)产生看似随机的输出。

修改

此结果当然与Igor Tandetnik引用的评论一致,引用cppreference.com

  

底层数组是const T [N]类型的临时数组,其中每个元素都是从原始初始化列表的相应元素进行复制初始化(除了缩小转换无效)。底层数组的生命周期与任何其他临时对象相同,除了从数组初始化initializer_list对象扩展了数组的生命周期,就像绑定对临时的引用一样(具有相同的例外,例如初始化非 - 静态班级成员)。底层数组可以在只读存储器中分配。

答案 1 :(得分:1)

  

[dcl.init.list] / 5 类型为std::initializer_list<E>的对象是从初始化列表构造的,就好像实现分配了N个元素类型的数组一样E,其中N是初始值设定项列表中的元素数。使用初始化列表的相应元素对该数组的每个元素进行复制初始化,并构造std::initializer_list<E>对象以引用该数组。

     

[dcl.init.list] / 6 数组的生命周期与initializer_list对象的生命周期相同。

最后一部分对您的示例非常重要。 array_to_init_list_helper返回原始initializer_list的副本 - 但基础数组的生命周期以原始数据的生命周期结束。副本指的是其生命周期已经结束的对象。然后,您的程序会显示未定义的行为。