2012-07-09 47 views
60

Mã:Tại sao hành vi initializer_list của C++ cho std :: vector và std :: array khác nhau?

std::vector<int> x{1,2,3,4}; 
std::array<int, 4> y{{1,2,3,4}}; 

Tại sao tôi cần dấu ngoặc nhọn kép cho mảng :: ::?

+1

Bạn có thực sự cần bộ niềng răng thứ hai cho 'std :: array' hay bạn chỉ nhận được cảnh báo? 'std :: mảng y {1,2,3,4};' hoạt động đối với tôi. – bames53

+3

@ bames53: GCC sai khi biên dịch. – Xeo

+10

@Xeo: không phải là "sai" để biên dịch một chương trình không đúng với cảnh báo. –

Trả lời

55

std::array<T, N> là tổng hợp: nó không có bất kỳ nhà xây dựng do người dùng khai báo nào, thậm chí không có một người đang tham gia std::initializer_list. Khởi tạo sử dụng niềng răng được thực hiện sử dụng tổng khởi, một tính năng của C++ đã được thừa hưởng từ C.

Các "cũ theo phong cách" khởi tạo tổng hợp sử dụng =:

std::array<int, 4> y = { { 1, 2, 3, 4 } }; 

Với phong cách cũ này tổng hợp khởi tạo, niềng răng bổ sung có thể được elided, vì vậy đây là tương đương với:

std::array<int, 4> y = { 1, 2, 3, 4 }; 

Tuy nhiên, những dấu ngoặc thêm chỉ có thể được elided "trong một tuyên bố của mẫu 0.123."(C++ 11 §8.5.1/11), nghĩa là khi sử dụng kiểu cũ =. Quy tắc này cho phép bỏ qua cú đúp không áp dụng cho việc khởi tạo danh sách trực tiếp. Một chú thích ở đây đọc: "Niềng răng không thể được elided trong sử dụng khác của danh sách khởi tạo."

Có báo cáo lỗi liên quan đến hạn chế này: CWG defect #1270. Nếu giải pháp đề xuất được thông qua, cú đúp sự bỏ bớt sẽ được phép cho các hình thức khác của danh sách khởi tạo, và sau đây sẽ được tốt được hình thành: (. Hat tip để Ville Voutilainen cho việc tìm kiếm các báo cáo lỗi)

std::array<int, 4> y{ 1, 2, 3, 4 }; 

+2

Tôi không biết điều này; tốt đẹp. – chris

+10

Vì vậy, nhiều cho "đồng bộ" khởi tạo ... – Mehrdad

+3

Vì vậy, nó là một thất bại của mô hình trừu tượng được trình bày cho 'mảng'? –

23

std::vector cung cấp một constructor mà mất trong một std::initializer_list<T>, trong khi std::array không có nhà thầu và các {1, 2, 3, 4} chuẩn bị tinh thần init-list là trong thực tế không hiểu như là một std::initializer_list, nhưng khởi tổng hợp cho mảng C-phong cách bên trong của std::array (đó là nơi bộ niềng răng thứ hai xuất phát từ: Một cho số std::array, một cho th e mảng thành phần kiểu C bên trong).

+0

Wow, tôi hiểu rồi, cảm ơn bạn :) – Sungmin

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