Copy elision adalah teknik optimisasi kompiler yang menghilangkan penyalinan / pemindahan objek yang tidak perlu.
Dalam keadaan berikut, kompiler diperbolehkan untuk menghilangkan operasi salin / pindah dan karenanya tidak memanggil konstruktor terkait:
- NRVO (Named Return Value Optimization) : Jika suatu fungsi mengembalikan tipe kelas dengan nilai dan ekspresi pernyataan pengembalian adalah nama objek yang tidak mudah menguap dengan durasi penyimpanan otomatis (yang bukan merupakan parameter fungsi), maka salin / pindahkan yang akan dilakukan oleh kompiler yang tidak mengoptimalkan dapat dihilangkan. Jika demikian, nilai yang dikembalikan dibangun langsung di penyimpanan yang nilai balik fungsinya akan dipindahkan atau disalin.
- RVO (Return Value Optimization) : Jika fungsi mengembalikan objek sementara tanpa nama yang akan dipindahkan atau disalin ke tujuan oleh kompiler naif, salinan atau perpindahan dapat dihilangkan sesuai 1.
#include <iostream>
using namespace std;
class ABC
{
public:
const char *a;
ABC()
{ cout<<"Constructor"<<endl; }
ABC(const char *ptr)
{ cout<<"Constructor"<<endl; }
ABC(ABC &obj)
{ cout<<"copy constructor"<<endl;}
ABC(ABC&& obj)
{ cout<<"Move constructor"<<endl; }
~ABC()
{ cout<<"Destructor"<<endl; }
};
ABC fun123()
{ ABC obj; return obj; }
ABC xyz123()
{ return ABC(); }
int main()
{
ABC abc;
ABC obj1(fun123());//NRVO
ABC obj2(xyz123());//NRVO
ABC xyz = "Stack Overflow";//RVO
return 0;
}
**Output without -fno-elide-constructors**
root@ajay-PC:/home/ajay/c++# ./a.out
Constructor
Constructor
Constructor
Constructor
Destructor
Destructor
Destructor
Destructor
**Output with -fno-elide-constructors**
root@ajay-PC:/home/ajay/c++# g++ -std=c++11 copy_elision.cpp -fno-elide-constructors
root@ajay-PC:/home/ajay/c++# ./a.out
Constructor
Constructor
Move constructor
Destructor
Move constructor
Destructor
Constructor
Move constructor
Destructor
Move constructor
Destructor
Constructor
Move constructor
Destructor
Destructor
Destructor
Destructor
Destructor
Bahkan ketika copy elision terjadi dan copy-/ move-constructor tidak dipanggil, itu harus ada dan dapat diakses (seolah-olah tidak ada optimasi yang terjadi sama sekali), jika tidak, program ini salah bentuk.
Anda harus mengizinkan elisi salinan seperti itu hanya di tempat-tempat di mana itu tidak akan mempengaruhi perilaku yang dapat diamati dari perangkat lunak Anda. Salinan salinan adalah satu-satunya bentuk optimasi yang diizinkan memiliki (yaitu elide) efek samping yang dapat diamati. Contoh:
#include <iostream>
int n = 0;
class ABC
{ public:
ABC(int) {}
ABC(const ABC& a) { ++n; } // the copy constructor has a visible side effect
}; // it modifies an object with static storage duration
int main()
{
ABC c1(21); // direct-initialization, calls C::C(42)
ABC c2 = ABC(21); // copy-initialization, calls C::C( C(42) )
std::cout << n << std::endl; // prints 0 if the copy was elided, 1 otherwise
return 0;
}
Output without -fno-elide-constructors
root@ajay-PC:/home/ayadav# g++ -std=c++11 copy_elision.cpp
root@ajay-PC:/home/ayadav# ./a.out
0
Output with -fno-elide-constructors
root@ajay-PC:/home/ayadav# g++ -std=c++11 copy_elision.cpp -fno-elide-constructors
root@ajay-PC:/home/ayadav# ./a.out
1
GCC menyediakan -fno-elide-constructors
opsi untuk menonaktifkan copy elision. Jika Anda ingin menghindari kemungkinan copy elision, gunakan -fno-elide-constructors
.
Sekarang hampir semua kompiler menyediakan elisi salinan saat optimasi diaktifkan (dan jika tidak ada opsi lain yang ditetapkan untuk menonaktifkannya).
Kesimpulan
Dengan setiap elisi salinan, satu konstruksi dan satu penghancuran salinan yang cocok dihilangkan, sehingga menghemat waktu CPU, dan satu objek tidak dibuat, sehingga menghemat ruang pada bingkai tumpukan.