2017-08-07 58 views
7

在考虑问题std::initializer list from already existing std::array without enumerating each element的解决方案时,我开发了类似bolov的机制,但没有构造对象,而只是构造器列表。我很惊讶我的解决方案不起作用,我无法弄清楚为什么。通过枚举值构造initializer_list包含随机值

#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值。

+1

['std :: initializer_list'](http://en.cppreference.com/w/cpp/utility/initializer_list)不是容器 - 它基本上只是一对指针。实际上,'array_to_init_list_helper'返回指向局部变量的指针。从文章:“复制'的std :: initializer_list'不会复制基础对象。” –

回答

1

穿过组件here(铛4.0.0)和/或here(GCC 7.1)去,很清楚的是,std::initializer_list使用悬挂指针,它(如大家都知道)产生看似随机的输出。

EDIT

该结果当然是与由Igor Tandetnik所作的注释行的,引用cppreference.com

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

+0

通过const引用返回initilizer list会改变什么? – Zereges

+0

@Zereges我不确定你的意思,但如果你的意思是改变返回值为'const std :: initializer_list &'那么这也不起作用。事实上,这将产生一个*临时*警告的引用,很可能是*分段错误*。 – Jonas

1

[dcl.init.list]/5std::initializer_list<E>类型的对象是从初始化列表构造为如果实现分配E类型,N元件的阵列,其中N是多少初始化程序列表中的元素。该数组的每个元素是复制初始化为初始化列表的相应元素,并且std::initializer_list<E>对象被构造来指代阵列。

[dcl.init.list]/6阵列的寿命是相同的initializer_list对象的。

这最后一部分是你的榜样很重要。 array_to_init_list_helper返回原始initializer_list的副本 - 但是潜在的阵列的寿命与原始的结束。该副本指的是其生命周期已经结束的对象。您的程序然后展示未定义的行为。