Вступ
Для технічного огляду - перейдіть до цієї відповіді .
Для поширених випадків, коли відбувається копіювання елізії, - перейдіть до цієї відповіді .
Копіювати elision - це оптимізація, реалізована більшістю компіляторів для запобігання додаткових (потенційно дорогих) копій у певних ситуаціях. Це робить повернення за вартістю або прохідною вартістю на практиці (застосовуються обмеження).
Це єдина форма оптимізації, що виключає (га!) Правило як би - копіювання elision можна застосувати, навіть якщо копіювання / переміщення об'єкта має побічні ефекти .
Наступний приклад, взятий з Вікіпедії :
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();
}
Залежно від компілятора та налаштувань, такі виходи є дійсними :
Привіт Світ!
Зроблено копію.
Зроблено копію.
Привіт Світ!
Зроблено копію.
Привіт Світ!
Це також означає, що можна створити менше об’єктів, тому ви також не можете покластися на певну кількість деструкторів, які викликаються. У вас не повинно бути критичної логіки всередині конструкторів копіювання / переміщення або деструкторів, так як ви не можете розраховувати на їх виклик.
Якщо виклик конструктора копіювання або переміщення відхилений, той конструктор повинен все ще існувати і бути доступним. Це гарантує, що елісія копіювання не дозволяє копіювати об'єкти, які зазвичай не можна копіювати, наприклад, тому що вони мають приватний або видалений конструктор копіювання / переміщення.
C ++ 17 : Станом на C ++ 17, копіювання Elision гарантується при поверненні об'єкта безпосередньо:
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
}