2011-08-25 36 views
8

Nel libro programmazione generica e STL (edizione cinese), si dice:costruttore o copia costruttore?

X x = X() chiamerà il costruttore di copia.

Sembra un po 'strano per me. E scrivo un programma di test come questo

#include <iostream> 

class Test { 

public: 

    Test() { 
     std::cout << "This is ctor\n"; 
    } 

    Test(const Test&) { 
     std::cout << "This is copy-ctor\n"; 
    } 

}; 

int main(int argc, char** argv) 
{ 

    Test t = Test(); 
    return 0; 
} 

L'uscita è "Questo è ctor". ok, ora sono confuso, che è giusto?

risposta

9

Nomalmente sì, un temporaneo è costruito di default, quindi viene richiamato il costruttore di copia per copiarlo nell'oggetto t.

Tuttavia, in pratica, la copia può essere ottimizzato fuori — anche se ha effetti collaterali (l'output della console):

[n3290: 8.5/16]: [..] In alcuni casi, un'implementazione è consentiti per eliminare la copia inerente a questa inizializzazione diretta costruendo il risultato intermedio direttamente nell'oggetto da inizializzare; vedi 12.2, 12.8.

E (in combinazione con l'esempio fornito nella stessa clausola):

[n3290: 12.2/2]: [..] Un'implementazione potrebbe utilizzare un temporaneo cui costruire X (2) prima di passare af() utilizzando il costruttore della copia ; in alternativa, nello spazio viene utilizzato lo spazio X(2) utilizzato per contenere l'argomento. [..]

Ma il costruttore di copia fa devono ancora esistere, anche se non potrebbe essere invocato.

In ogni caso, se si compila con ottimizzazioni spento (o, con GCC, possibilmente -fno-elide-constructors), si vedrà:

This is ctor 
This is copy-ctor 
+2

In gcc, potrebbe essere necessario utilizzare '-fno-elide-constructors', poiché anche' -O0' non impedisce l'elision, penso. –

+0

@Kerrek: Grazie! –

+0

La copia può essere eliminata anche quando non è * banale *, la copia viene eliminata costruendo il provvisorio al posto della variabile locale. La complessità dell'oggetto o della copia è irrilevante per tale ottimizzazione. –

4

In teoria, X x = X() chiamerà il costruttore di default per creare un oggetto temporaneo, e copialo in x usando il costruttore di copie. In pratica, i compilatori possono saltare direttamente la parte di costruzione della copia e il costrutto predefinito x (che, come sottolinea David nel suo commento, richiede comunque che il costruttore di copie sia sintatticamente accessibile, comunque). La maggior parte dei compilatori lo fa almeno quando le ottimizzazioni sono abilitate.

+4

È importante notare che il costruttore di copie deve essere disponibile, anche se la copia è stata eliminata. Cioè, se non è accessibile, il compilatore rifiuterà la riga con un errore. –

+0

@David: hai ragione. L'ho incorporato nella mia risposta. Grazie per averlo portato. – sbi

2

Questo è un caso in cui un modulo di Return Value Optimisation(RVO) (noto anche come Copy Elision) può aiutare molto sull'ottimizzazione. La pagina wikipedia collegata ha un'ottima spiegazione di cosa sta succedendo.

+3

Non penso che sia assolutamente corretto. Non c'è chiamata di funzione qui che restituisca un 'X' (ricorda che i costruttori non hanno valori di ritorno). Questa è la copia elisione, che è un concetto correlato, ma distinto. –

+0

Sono d'accordo. Questo non è strettamente RVO (anche se è correlato). –

+0

@Tomak: anche questo non è del tutto errato. Questa è una variante di * quel tipo * di ottimizzazione. +1 per controbilanciare il downvote. –

Problemi correlati