2017-08-07 68 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的副本 - 但是潛在的陣列的壽命與原始的結束。該副本指的是其生命週期已經結束的對象。您的程序然後展示未定義的行爲。