2012-07-09 19 views
60

Kod:Dlaczego zachowanie inicjalizatora listy C++ dla std :: vector i std :: array jest inne?

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

Dlaczego muszę podwójnych nawiasów klamrowych dla std :: tablicy?

+1

Czy rzeczywiście potrzebujesz drugiego zestawu nawiasów klamrowych dla 'std :: array', czy dostajesz ostrzeżenie? 'std :: array y {1,2,3,4};' działa dla mnie. – bames53

+3

@ bames53: GCC jest źle w kompilacji. – Xeo

+10

@Xeo: nie jest "źle" skompilowanie źle sformułowanego programu z ostrzeżeniem. –

Odpowiedz

55

std::array<T, N> jest agregatem: nie ma żadnych konstruktorów zadeklarowanych przez użytkownika, ani jednego, który pobiera std::initializer_list. Inicjalizacji za pomocą szelek odbywa się za pomocą łączną inicjalizacji, funkcja C++, który został odziedziczony z C

w „starym stylu” kruszywa inicjalizacji używa =:

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

Z tym starym stylu kruszywo inicjalizacji, dodatkowe szelki mogą być pomijana, więc jest to równoznaczne z:

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

jednak te dodatkowe szelki mogą być pomijana tylko „w deklaracji formularza T x = { a }; "(C++ 11 §8.5.1/11), to znaczy, gdy używany jest stary styl =. Ta reguła umożliwiająca eliminację klamr nie ma zastosowania do bezpośredniej inicjalizacji list. Przypis w tym miejscu brzmi: "Szelki nie mogą zostać usunięte z innych sposobów inicjowania listy".

Istnieje raport o usterce dotyczący tego ograniczenia: CWG defect #1270. Jeśli proponowana uchwała zostanie przyjęta, klamra elizja zostaną dopuszczone do innych form liście inicjalizacji, oraz dodaje się będzie dobrze uformowane: (. Cynk kapelusza do Ville Voutilainen za znalezienie raport awaryjności)

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

+2

Nie wiedziałem tego; miły. – chris

+10

Tyle jeśli chodzi o "jednolitą" inicjalizację ... – Mehrdad

+3

A więc jest to porażka modelu abstrakcji prezentowanego dla 'array'? –

23

Ponieważ std::vector oferuje konstruktora, że ​​trwa w std::initializer_list<T>, natomiast std::array ma konstruktorów i usztywnione startowe lista {1, 2, 3, 4} w rzeczywistości nie jest interpretowany jako std::initializer_list, ale łączna inicjalizacji do wewnętrznej tablicy C-styl std::array (to gdzie drugi zestaw nawiasów pochodzi z: Jeden dla std::array, jeden dla th e wewnętrzna tablica członków w stylu C).

+0

Wow, mam to, dziękuję :) – Sungmin

Powiązane problemy