2015-12-21 12 views
39

Penso che abbia molte informazioni a riguardo ma non so come si chiami. Non riesco a capire la differenza tra i prossimi due stringhe di codice:Qual è la differenza tra Object obj = Object() e Object obj()?

Object obj(); 

E

Object obj = Object(); 

si può spiegare? O almeno dì come chiamarlo.

+0

Ok, perché ho un problema quando uso 'Object obj()' ma non ottengo quando uso 'Object obj = Object()'? –

+0

@ghostman bene dovresti usare 'Object obj;', senza parentesi – dabadaba

+3

@juanchopanza ora che ho notato che le parentesi hai ragione, sono diverse. Ho pensato che OP avesse detto 'Object obj', non' Object obj() '. – dabadaba

risposta

49
Object obj(); 

non è un'istanza di oggetto, è una dichiarazione di una funzione obj che non prende argomenti e restituisce un'istanza di Object .

Object obj; 

è un default initialization, cioè istanziazione con il costruttore implicito (quindi, costruttore di default implicito o definite dall'utente non explicit costruttore senza parametri), e questa dichiarazione chiamate costruttori implicite di-POD non Object membri, e per I tipi POD non li inizializza (non verranno azzerati). Questo è giusto per i membri dei membri di Object e così via in modo ricorsivo.

Object obj{}; 

è un elenco di inizializzazione o aggregato inizializzazione (se Object è un aggregato). Quelli chiamati in modo diverso, per parentesi vuote, il comportamento è lo stesso: tutti i membri dei tipi POD sono inizializzati a zero e i non-POD sono inizializzati di default.

Object obj = Object(); 

teoricamente è una dichiarazione in due fasi: 1) creare temporanea Object esempio; 2) quindi costruisci obj da copy constructor/move constructor/copy operator/move operator. Ma in pratica sarà costruito di default con in mente copy/move-elision (è abilitato su tutti i moderni compilatori di default anche con tutte le ottimizzazioni disattivate, è necessario disabilitare esplicitamente elision). Meglio non usare questa variante.

Pre-Conclusione

Scegli

Object obj; 

o

Object obj{}; 

Scegli primo luogo se volete l'inizializzazione veloce senza zeroifying suoi POD-soci. Scegli un secondo se vuoi essere sicuro che tutti i suoi membri POD saranno zero dopo l'istanziazione di Object.

Praticamente, prima del primo che legge dai suoi membri, entrambe le varianti hanno la stessa velocità in runtime su tutti i sistemi operativi moderni.

Quindi ...

Conclusione

Usa valore di inizializzazione:

Object obj{}; 

a meno che non hai bisogno di una performance in tempo reale su sistemi esotici.

+0

Grazie per la spiegazione! –

+1

Si noti che 'Object obj {};' è una funzionalità di C++ 11 e non era disponibile nelle versioni precedenti.Ho avuto a che fare con questo regolarmente, come parte del nostro codice sorgente è condivisa da un altro team che per ragioni tecniche usa ancora C++ 09, quindi qualsiasi file comune a entrambi i progetti non può usare questa notazione. –

+0

@DarrelHoffman Andiamo, è la fine del 2015 oggi! C++ 14 è uno standard, C++ 17 in arrivo. – vladon

21
Object obj(); 

dichiara una nomi delle funzioni obj che restituisce un Object e non accetta parametri. Questo non è generalmente quello che vuoi.

Object obj = Object(); 

dichiara un Object nome obj allora è copia inizializzato con un valore predefinito temporanea costruita Object. Normalmente non si desidera eseguire questa operazione a meno che non si reimposti un oggetto su uno stato predefinito.

In generale, se si vuole costruire senza chiamare un costruttore è possibile utilizzare

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

Grazie per la risposta anticipata! –

+4

'Oggetto obj {};' è l'inizializzazione del valore, non l'inizializzazione predefinita. Questo può fare la differenza in alcuni casi. – juanchopanza

8

grande differenza.

Il primo è una funzione prototipo di una funzione che non accetta argomenti e restituisce un oggetto.

Il secondo crea un'istanza chiamando il costruttore predefinito. A scanso di equivoci, l'operatore di assegnazione non viene chiamato.

Rilasciare le parentesi nel primo caso per rendere equivalenti le istruzioni.

+0

L'eliminazione della parentesi non rende le istruzioni equivalenti! 'Object obj = Object();' crea un'istanza temporanea di Object, quindi copia-costruisce obj da temporary. Nella maggior parte dei casi ci sarà copy-elision, ma ci sono rari casi in cui ciò ha senso. – vladon

+3

Il secondo copia/sposta costruisce 'obj' da un temporaneo. Questo è diverso perché non verrà compilato se l'oggetto non è MoveConstructible. Inoltre, se è mobile, può avere un comportamento diverso da 'Object obj;' anche se sarebbe considerato uno stile sbagliato per scrivere codice che ha un comportamento diverso. –

31
Object obj(); 

dichiara una funzione, non un oggetto! Questa è un'istanza di "Most Vexing Parse".

Object obj = Object(); 

richiede Object avere un costruttore mossa accessibile o copiare costruttore (anche se il compilatore potrebbe finire elisione movimento/copia).

Semplici modi per creare solo un oggetto includono:

Object obj; 
Object obj{}; 
+0

Grazie! Ho capito, non lo so. –

+4

'Oggetto obj;' e 'Oggetto obj {};' sono diversi. – vladon

+1

Sì, sono ... – aschepler

Problemi correlati