2015-12-21 19 views
39

Myślę, że ma wiele informacji na ten temat, ale nie wiem jak to się nazywa. Nie mogę zrozumieć różnicę między najbliższych dwóch ciągów kodu:Jaka jest różnica między Object obj = Object() i Object obj()?

Object obj(); 

I

Object obj = Object(); 

Czy możesz wyjaśnić? Lub przynajmniej powiedz jak to nazwać.

+0

OK, dlaczego pojawia się problem, gdy używam 'Object obj()', ale nie otrzymuję kiedy używam 'Object obj = Object()'? –

+0

@ghostman dobrze powinieneś używać 'Object obj;', bez nawiasów – dabadaba

+3

@juanchopanza teraz, gdy zauważyłem nawiasy, masz rację, są różne. Zakładam, że OP powiedział: "Object obj", a nie "Object obj()". – dabadaba

Odpowiedz

49
Object obj(); 

nie jest instancji obiektu, jest to deklaracja z funkcji obj który nie wymaga żadnych argumentów i zwraca instancję Object .

Object obj; 

jest default initialization, czyli instancji z niejawny konstruktor (czyli domyślnej niejawny konstruktora lub zdefiniowanej przez użytkownika non explicit konstruktora bez parametrów), a ta deklaracja wzywa ukryte konstruktorów non-POD Object członków, a dla POD-types nie inicjuje ich (nie zostaną wyzerowane). To jest odpowiednie dla członków członków Object i tak dalej rekursywnie.

Object obj{}; 

jest inicjalizacji lista lub kruszywo inicjalizacji (jeśli Object jest agregatem). Te, które nazwano inaczej, dla pustych nawiasów, zachowanie jest takie samo: wszyscy członkowie typów POD są inicjowani od zera, a nie-POD są inicjowane domyślnie.

Object obj = Object(); 

teoretycznie jest dwuetapową instrukcją: 1) utworzyć tymczasową instancję Object; 2) następnie skonstruuj obiekt przez konstruktora copy/move/operator copy/move. Ale w praktyce będzie on domyślnie skonstruowany z myślą o kopiowaniu/elizacji ruchu (domyślnie jest włączony we wszystkich nowoczesnych kompilatorach, nawet przy wyłączonych optymalizacjach, należy jawnie wyłączyć elizację). Lepiej nie używaj tego wariantu.

Wstępnie Wnioski

Wybierz

Object obj; 

lub

Object obj{}; 

Wybierz najpierw, jeśli chcesz szybki inicjalizacji ze nie zeroifying jego POD członków. Wybierz drugie, jeśli chcesz mieć pewność, że po powieleniu Object wszyscy jego członkowie POD będą zerowi.

Praktycznie przed pierwszym czytającym od jego członków, oba warianty mają taką samą prędkość w czasie wykonywania na wszystkich nowoczesnych systemach operacyjnych.

Więc ...

Wnioski

Wykorzystanie wartości inicjalizacji:

Object obj{}; 

chyba trzeba wydajności w czasie rzeczywistym na egzotycznych systemów.

+0

Dziękuję za wyjaśnienie! –

+1

Należy zauważyć, że 'Object obj {};' jest funkcją C++ 11 i nie był dostępny we wcześniejszych wersjach.Miałem do czynienia z tym regularnie, ponieważ część naszego kodu źródłowego jest udostępniana przez inny zespół, który z przyczyn technicznych wciąż używa C++ 09, więc żadne pliki wspólne dla obu projektów nie mogą korzystać z tej notacji. –

+0

@DarrelHoffman Daj spokój, już koniec 2015! C++ 14 jest standardem, nadchodzi C++ 17. – vladon

21
Object obj(); 

Deklaruje nazwy funkcji obj zwracającą Object i nie bierze parametry. Zasadniczo nie jest to, czego chcesz.

Object obj = Object(); 

deklaruje Object nazwie obj następnie kopia jest inicjowany z tymczasowym domyślnie skonstruowany Object. Zwykle nie chcesz tego robić, dopóki nie zresetujesz obiektu do stanu domyślnego.

Generalnie, jeśli chcesz zbudować bez wywoływania konstruktora można użyć

Object obj; 
//or 
Object obj{}; 
+0

Dziękuję za odpowiedź zaawansowaną! –

+4

'Object obj {};' jest inicjacją wartości, a nie domyślną inicjalizacją. W niektórych przypadkach może to mieć znaczenie. – juanchopanza

8

duża różnica.

Pierwszy to prototyp funkcji do funkcji nie pobierającej argumentów i zwracającej obiekt.

Druga inicjuje obiekt, wywołując domyślny konstruktor. W celu uniknięcia wątpliwości operator przydziału nie jest wywoływany.

Upuść nawiasy w pierwszym przypadku, aby wyciągi były równoważne.

+0

Upuszczenie nawiasu nie powoduje, że instrukcje są równoważne! 'Object obj = Object(); tworzy tymczasową instancję obiektu, a następnie kopiuje-konstruuje obiekt z pliku tymczasowego. W większości przypadków będzie to eliksir kopiowania, ale są rzadkie przypadki, w których ma to sens. – vladon

+3

Druga kopia/move konstruuje 'obj' z tymczasowego. Jest inaczej, ponieważ nie będzie kompilacji, jeśli obiekt nie jest MoveConstructible. Ponadto, jeśli jest ruchomy, może mieć inne zachowanie niż "Object obj;", chociaż byłoby źle napisać kod, który ma inne zachowanie. –

31
Object obj(); 

deklaruje funkcję, a nie obiekt! Jest to instancja "Najbardziej parodiującej parse".

Object obj = Object(); 

wymaga Object mieć dostępną konstruktora przenieść lub skopiować konstruktora (chociaż kompilator może skończyć eliding Move/Copy).

Proste sposoby, aby po prostu utworzyć obiektu należą:

Object obj; 
Object obj{}; 
+0

Dziękujemy! Zrozumiałem, nie wiem o tym. –

+4

'Object obj;' i 'Object obj {};' są różne. – vladon

+1

Tak, są ... – aschepler

Powiązane problemy