Domanda

Di recente ho scritto un pezzo di codice che lo ha fatto

SomeClass someObject;
mysqlpp::StoreQueryResult result = someObject.getResult();

dove SomeClass :: getResult () assomiglia a:

mysqlpp::StoreQueryResult SomeClass::getResult()
{
mysqlpp::StoreQueryResult res = ...<something>...;
return res;
}

Ora, usando l'esempio nel primo frammento di codice, quando ho compilato ed eseguito il programma si è bloccato con un segnale ABORT. Ho quindi modificato il primo snippet in:

SomeClass someObject;
mysqlpp::StoreQueryResult result(someObject.getResult());

che ha funzionato bene. Inoltre, solo per provarlo, l'ho cambiato di nuovo in:

SomeClass someObject;
mysqlpp::StoreQueryResult result;
result = someObject.getResult();

che ha funzionato bene.

Ora, non riesco proprio a capire perché il primo esempio sia fallito e i successivi due abbiano avuto successo. A quanto ho capito, nel primo esempio, il costruttore della copia viene utilizzato per inizializzare il risultato. Ma non è così anche nel secondo esempio? Allora perché il secondo esempio è riuscito? Il terzo esempio ha un po 'più senso - poiché la const della copia non viene utilizzata, assegniamo solo dopo la costruzione.

In breve, qual è la differenza tra:

FooClass a = someObject.someMethodReturningFooClassInstance();

e

FooClass a(someObject.someMethodReturningFooClassInstance());?

Grazie mille!

È stato utile?

Soluzione

Non credo che ci sia alcuna differenza nei due casi. Lo stesso costruttore di copie viene chiamato entrambe le volte.

Sei sicuro che sia esattamente ciò che hai scritto nel tuo codice?

Altri suggerimenti

A rigor di termini nel primo caso viene chiamato il costruttore predefinito seguito dall'operatore di assegnazione e nel secondo caso utilizza solo il costruttore di copia.

Okay, la mia ipotesi iniziale era sbagliata, e apparentemente in entrambi i casi sarebbe stato chiamato solo il costruttore di copie (anche nel caso di assegnazione potrebbe essere chiamato anche un costruttore aggiuntivo di "conversione"). Accenderò il compilatore dopo un po 'di sonno e lo verificherò nel mio ambiente di sviluppo.

Potresti semplicemente inserire un punto di interruzione (o persino un'istruzione printf) all'interno del costruttore della copia, e sapresti esattamente quando è stato chiamato, lo sai. SO non può sostituire il debug di base. ;)

Ma sì, il costruttore della copia dovrebbe essere chiamato nei due primi casi. Il terzo caso utilizza invece l'operatore di assegnazione.

Hai provato a eseguirlo nel debugger? Dovrebbe rompersi su un segnale ABORT.

Bene, in realtà il primo eseguirà una copia intermedia con operator =, mentre il secondo eseguirà un costrutto di copia diretta.

Penso che al primo caso sia assegnato il valore (valore giusto) all'oggetto. Si tratta di inviare il valore all'oggetto.In 2,3 esempio è l'oggetto implicito e il concetto di oggetto esplicito. Non si deve scrivere il codice per valore assegnato sull'oggetto diretto.

Nella teoria più pura, il costruttore di copie dovrebbe essere chiamato in entrambi i casi. Tuttavia, esiste qualcosa chiamato Return Value Optimization (RVO) che il compilatore può utilizzare in questi casi. Se si utilizza RVO, il costruttore della copia non verrà chiamato. Forse il tuo compilatore utilizza RVO in un caso e non nell'altro?

Modifica: Questo vale solo per il caso

SomeClass someObject;
mysqlpp::StoreQueryResult result;
result = someObject.getResult();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top