Einführung
Für einen technischen Überblick - Überspringen Sie diese Antwort .
Für häufige Fälle, in denen die Kopie weggelassen wird - Überspringen Sie diese Antwort .
Copy Elision ist eine Optimierung, die von den meisten Compilern implementiert wird, um in bestimmten Situationen zusätzliche (potenziell teure) Kopien zu vermeiden. Sie macht die Rückgabe nach Wert oder die Weitergabe nach Wert in der Praxis möglich (es gelten Einschränkungen).
Es ist die einzige Form der Optimierung, die die Als-ob-Regel ausschließt (ha!). Kopierelimination kann auch dann angewandt werden, wenn das Kopieren/Verschieben des Objekts Nebeneffekte hat .
Das folgende Beispiel stammt aus 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();
}
Je nach Compiler und Einstellungen werden die folgenden Ergebnisse ausgegeben sind alle gültig :
Hallo Welt!
Eine Kopie wurde angefertigt.
Eine Kopie wurde angefertigt.
Hallo Welt!
Eine Kopie wurde angefertigt.
Hallo Welt!
Dies bedeutet auch, dass weniger Objekte erstellt werden können, so dass man sich auch nicht darauf verlassen kann, dass eine bestimmte Anzahl von Destruktoren aufgerufen wird. Sie sollten keine kritische Logik innerhalb von Kopier-/Verschiebe-Konstruktoren oder -Destruktoren haben, da Sie sich nicht darauf verlassen können, dass diese aufgerufen werden.
Wenn ein Aufruf eines Kopier- oder Verschiebekonstruktors elidiert wird, muss dieser Konstruktor noch existieren und zugänglich sein. Damit wird sichergestellt, dass das Kopieren von Objekten, die normalerweise nicht kopierbar sind, z. B. weil sie einen privaten oder gelöschten Kopier-/Verschiebekonstruktor haben, nicht möglich ist.
C++17 : Ab C++17 ist Copy Elision garantiert, wenn ein Objekt direkt zurückgegeben wird:
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
}