2017-08-07 23 views
7

Trong khi suy nghĩ về giải pháp cho câu hỏi std::initializer list from already existing std::array without enumerating each element, tôi đã phát triển cơ chế tương tự như bolov đã làm, nhưng không xây dựng các đối tượng, nhưng danh sách initializer thay vì chỉ. Tôi đã rất ngạc nhiên khi giải pháp của tôi không hoạt động và tôi không thể hiểu tại sao.Xây dựng initializer_list bằng cách liệt kê các giá trị chứa các giá trị ngẫu nhiên

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

Tôi getting random values, trong khi tôi mong chờ để có được giá trị của arr.

+1

['std :: initializer_list'] (http://en.cppreference.com/w/cpp/utility/initializer_list) không phải là vùng chứa - về cơ bản chỉ là một cặp con trỏ. Trong thực tế, 'array_to_init_list_helper' trả về con trỏ tới các biến cục bộ. Từ bài viết: "Sao chép một' std :: initializer_list' không sao chép các đối tượng cơ bản. " –

Trả lời

1

Đi qua cụm here (clang 4.0.0) và/hoặc here (GCC 7.1), rõ ràng là std::initializer_list đang sử dụng con trỏ lơ lửng

EDIT

Kết quả này là dĩ nhiên phù hợp với nhận xét của Igor Tandetnik, trích dẫn cppreference.com:

Mảng cơ bản là một mảng tạm thời kiểu const T [N], trong mà mỗi phần tử được sao chép-khởi tạo (ngoại trừ việc thu hẹp chuyển đổi không hợp lệ) từ phần tử tương ứng của danh sách khởi tạo ban đầu. Tuổi thọ của mảng cơ bản giống như bất kỳ đối tượng tạm thời nào khác, ngoại trừ việc khởi tạo đối tượng initializer_list từ mảng mở rộng vòng đời của mảng chính xác như ràng buộc tham chiếu đến một tạm thời (với cùng ngoại lệ, chẳng hạn như để khởi tạo một non thành viên đẳng cấp). Mảng cơ bản có thể được cấp phát trong bộ nhớ chỉ đọc.

+0

Sẽ trở về bằng tham chiếu const đến danh sách initilizer thay đổi bất cứ điều gì? – Zereges

+0

@Zereges Tôi không chắc chắn ý bạn là gì, nhưng nếu bạn muốn thay đổi giá trị trả về thành 'const std :: initializer_list &' thì điều đó cũng không hoạt động. Trên thực tế, điều này sẽ tạo ra một tham chiếu * trả về cho cảnh báo tạm thời * và có thể là lỗi * phân đoạn *. – Jonas

1

[dcl.init.list]/5 Một đối tượng của loại std::initializer_list<E> được xây dựng từ một danh sách initializer như thể việc thực hiện phân bổ một mảng của N phần tử kiểu E, nơi N là số các phần tử trong danh sách khởi tạo. Mỗi phần tử của mảng đó được sao chép-khởi tạo với phần tử tương ứng của danh sách khởi tạo và đối tượng std::initializer_list<E> được xây dựng để tham chiếu đến mảng đó.

[dcl.init.list]/6 Tuổi thọ của mảng giống với đối tượng initializer_list.

Phần cuối cùng này quan trọng đối với ví dụ của bạn. array_to_init_list_helper trả về bản sao của initializer_list gốc - nhưng thời gian tồn tại của mảng cơ bản kết thúc bằng bản sao của bản gốc. Bản sao đề cập đến đối tượng có thời gian đã kết thúc. Chương trình của bạn sau đó thể hiện hành vi không xác định.

Các vấn đề liên quan