Sesuatu yang menggangguku tentang:
MyClass& operator=(const MyClass& other)
{
MyClass tmp(other);
swap(tmp);
return *this;
}
Pertama, membaca kata "swap" ketika pikiran saya memikirkan "salinan" mengganggu akal sehat saya. Juga, saya mempertanyakan tujuan dari trik mewah ini. Ya, pengecualian apa pun dalam membangun sumber daya baru (disalin) harus terjadi sebelum pertukaran, yang tampaknya merupakan cara yang aman untuk memastikan semua data baru diisi sebelum membuatnya ditayangkan.
Tidak apa-apa. Jadi, bagaimana dengan pengecualian yang terjadi setelah penukaran? (ketika sumber daya lama dihancurkan ketika objek sementara keluar dari ruang lingkup) Dari perspektif pengguna tugas, operasi gagal, kecuali tidak. Ini memiliki efek samping yang besar: salinan itu benar-benar terjadi. Hanya beberapa pembersihan sumber daya yang gagal. Keadaan objek tujuan telah diubah meskipun operasi dari luar tampaknya gagal.
Jadi, saya mengusulkan daripada "swap" untuk melakukan "transfer" yang lebih alami:
MyClass& operator=(const MyClass& other)
{
MyClass tmp(other);
transfer(tmp);
return *this;
}
Masih ada konstruksi objek sementara, tetapi tindakan segera berikutnya adalah membebaskan semua sumber daya tujuan saat ini sebelum memindahkan (dan NULLing sehingga mereka tidak akan membebaskan dua kali) sumber daya dari sumber itu.
Alih-alih {membangun, memindahkan, merusak}, saya mengusulkan {membangun, merusak, memindahkan}. Tindakan, yang merupakan tindakan paling berbahaya, adalah tindakan yang dilakukan terakhir setelah segala sesuatu diselesaikan.
Ya, kerusakan gagal adalah masalah di kedua skema. Data bisa rusak (disalin ketika Anda tidak mengira itu) atau hilang (dibebaskan ketika Anda tidak mengira itu). Hilang lebih baik dari pada rusak. Tidak ada data yang lebih baik dari data buruk.
Transfer, bukan swap. Itu saran saya.