Wprowadzenie
Przegląd techniczny - przejdź do tej odpowiedzi .
W typowych przypadkach, w których występuje usuwanie kopii, przejdź do tej odpowiedzi .
Eliminacja kopiowania to optymalizacja realizowana przez większość kompilatorów w celu zapobiegania dodatkowym (potencjalnie drogim) kopiom w niektórych sytuacjach. W praktyce umożliwia to zwrot według wartości lub według wartości (obowiązują ograniczenia).
Jest to jedyna forma optymalizacji, która wymusza (ha!) Zasadę „jak gdyby” - można zastosować eliminację kopiowania, nawet jeśli kopiowanie / przenoszenie obiektu ma skutki uboczne .
Poniższy przykład pochodzi z Wikipedii :
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();
}
W zależności od kompilatora i ustawień wszystkie poniższe dane wyjściowe są prawidłowe :
Witaj świecie!
Kopia została wykonana.
Kopia została wykonana.
Witaj świecie!
Kopia została wykonana.
Witaj świecie!
Oznacza to również, że można utworzyć mniej obiektów, więc nie można również polegać na wywołaniu określonej liczby niszczycieli. Nie powinieneś mieć krytycznej logiki wewnątrz konstruktorów kopiowania / przenoszenia lub destruktorów, ponieważ nie możesz polegać na ich wywoływaniu.
Jeśli zostanie wywołane wywołanie konstruktora kopiowania lub przenoszenia, konstruktor ten musi nadal istnieć i musi być dostępny. Zapewnia to, że usuwanie kopii nie pozwala na kopiowanie obiektów, których normalnie nie można skopiować, np. Ponieważ mają one prywatny lub usunięty konstruktor kopiowania / przenoszenia.
C ++ 17 : Począwszy od C ++ 17, Copy Elision jest gwarantowane, gdy obiekt jest zwracany bezpośrednio:
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
}