introduzione
Per una panoramica tecnica, passa a questa risposta .
Per i casi più comuni in cui si verifica l'eliminazione della copia, passare a questa risposta .
Copy elision è un'ottimizzazione implementata dalla maggior parte dei compilatori per impedire copie extra (potenzialmente costose) in determinate situazioni. Rende possibile in pratica la restituzione per valore o pass-by-value (si applicano restrizioni).
È l'unica forma di ottimizzazione che elide (ha!) La regola as-if - la copia dell'elisione può essere applicata anche se la copia / spostamento dell'oggetto ha effetti collaterali .
Il seguente esempio tratto da Wikipedia :
struct C {
C() {}
C(const C&) { std::cout << "A copy was made.\n"; }
};
C f() {
return C();
}
int main() {
std::cout << "Hello World!\n";
C obj = f();
}
A seconda del compilatore e delle impostazioni, sono validi tutti i seguenti output :
Ciao mondo!
È stata fatta una copia.
È stata fatta una copia.
Ciao mondo!
È stata fatta una copia.
Ciao mondo!
Ciò significa anche che è possibile creare un numero inferiore di oggetti, quindi non è possibile fare affidamento su un numero specifico di distruttori chiamati. Non dovresti avere una logica critica all'interno di costruttori / distruttori di copia / spostamento, poiché non puoi fare affidamento sul fatto che vengano chiamati.
Se viene elusa una chiamata a un costruttore di copia o spostamento, tale costruttore deve ancora esistere e deve essere accessibile. Ciò garantisce che l'eliminazione della copia non consenta di copiare oggetti che non sono normalmente copiabili, ad esempio perché hanno un costruttore di copia / spostamento privato o cancellato.
C ++ 17 : A partire da C ++ 17, Copy Elision è garantito quando un oggetto viene restituito direttamente:
struct C {
C() {}
C(const C&) { std::cout << "A copy was made.\n"; }
};
C f() {
return C(); //Definitely performs copy elision
}
C g() {
C c;
return c; //Maybe performs copy elision
}
int main() {
std::cout << "Hello World!\n";
C obj = f(); //Copy constructor isn't called
}