2009-12-08 11 views
12

Czy istnieje zasada, aby zdecydować, kiedy użyć starej składni () zamiast nowej składni {}?Jednolita inicjalizacja w C++ 0x, kiedy użyć() zamiast {}?

Aby zainicjować struct:

struct myclass 
{ 
    myclass(int px, int py) : x(px), y(py) {} 
private: 
    int x, y; 
}; 
... 
myclass object{0, 0}; 

Teraz w przypadku vector na przykład, ma wiele konstruktorów. Ilekroć wykonaj następujące czynności:

vector<double> numbers{10}; 

dostaję wektor elementu zamiast jednego z elementów jako jeden z konstruktorów jest:

explicit vector (size_type n, const T& value= T(), const Allocator& = Allocator()); 

Podejrzewam, że ilekroć Klasa definiuje konstruktor initializer list, podobnie jak w przypadku wektora, wywoływana jest ze składnią {}.

Czyli to jest prawidłowe. tj. Czy powinienem powrócić do starej składni tylko wtedy, gdy klasa definiuje konstruktor listy inicjalizatorów, aby wywoływał inny konstruktor? np. skorygować powyższy kod:

vector<double> numbers(10); // 10 elements instead of just one element with value=10 
+6

Czy to oznacza, że ​​można łamać klientów klas podczas dodawania konstruktorów listy inicjalizatorów? Oooo. –

+2

Nie, konstruktor inicjatora nie ma wpływu na inne konstruktory w miejscu AFAIK. –

+1

@dribeas: Czy to pewne. Załóżmy, że twoja klasa ma początkowo konstruktor, który przyjmuje pojedynczy argument int i z przyjemnością tworzysz instancje z nową składnią. Jeśli zostanie dodany nowy konstruktor, który pobiera 'initializer_list ', czy wszystkie te obiekty nie będą teraz używać dodanego konstruktora? Dopóki przykłady w sieci nie są aktualne i deklaracja wektora z listą powinna wyglądać jak wektor ' v {{2, 1}};' Nie widzę żadnych nawiasów. – UncleBens

Odpowiedz

2

spojrzeć na to:

http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=453&rll=1

Zastosowanie {} -Style inicjalizatorów na zmiennej nie ma bezpośredniego odwzorowania na listach startowych na wszelkie konstruktorów klasy. Te listy inicjalizacji konstruktora można dodawać/usuwać/modyfikować bez zrywania istniejących rozmówców.

Zasadniczo różne zachowanie kontenera jest specjalne i wymaga specjalnego kodu w tym kontenerze, w szczególności konstruktora wykonującego numer std::initializer_list. W przypadku obiektów POD i prostych można używać zamiennie {} i ().

+0

"W przypadku POD i prostych obiektów można używać {} i() zamiennie." Nie, '()' działa tylko wtedy, gdy istnieje konstruktor, który (poza konstruktorem kopiowania) dyskwalifikuje obiekt z POD. '{}' z drugiej strony wciąż działa. – Potatoswatter

9

Znalazłem odpowiedź w standardowych dokumentach (latest draft). Mam nadzieję, że spróbuję wyjaśnić, co rozumiem.

Po pierwsze, jeśli klasa definiuje konstruktor listy inicjalizacji, a następnie jest on stosowany, gdy odpowiednia:

§ 8.5.4 (strona 203)

Initializer-lista konstruktorzy są preferowane przez inni konstruktorzy w inicjalizacji listy listy (13.3.1.7).

Myślę, że to wspaniała cecha mieć, eliminując ból głowy związany z niejednorodnego stylu :)

W każdym razie, tylko haczyka (co jest moje pytanie o) jest, że jeśli zaprojektuj klasę bez konstruktora inicjalizatora, potem dodaj ją później, możesz uzyskać zaskakujący wynik.

Zasadniczo wyobrazić std::vector nie ma konstruktora inicjator listy, a następnie dodaje stworzyłoby wektor z 10 elementów:

std::vector<int> numbers{10}; 

Dodając konstruktora listy inicjator, kompilator będzie sprzyjać go nad drugim konstruktor z powodu składni {}. Takie zachowanie mogłoby się zdarzyć, ponieważ elementy listy inicjującej zostały zaakceptowane przy użyciu konstruktora listy init. Jeśli nie ma akceptowalnej konwersji, należy użyć innego konstruktora, np .:

std::vector<string> vec{10}; 
// a vector of 10 elements. 
// the usual constructor got used because "{0}" 
// is not accepted as an init-list of type string.