Üç Kuralı: Bir sınıf bir kaynak yönetiyorsa (örneğin, bellek), aşağıdaki yöntemlerden birinin açıkça uygulanması durumunda diğerlerinin de uygulanması gerekir:
C++11: Beş Kuralı – taşınabilir işlemler eklendi:
Bu kuralın ihlali, kaynak sahipliği hatalarına yol açar, örneğin çift silme veya bellek sızıntısı gibi.
class Buffer { char* data; public: Buffer(size_t sz) : data(new char[sz]) {} ~Buffer() { delete[] data; } Buffer(const Buffer& other) : data(new char[strlen(other.data)+1]) { strcpy(data, other.data); } Buffer& operator=(const Buffer& other) { if (&other != this) { delete[] data; data = new char[strlen(other.data)+1]; strcpy(data, other.data); } return *this; } // C++11+ için taşıma semantiği: Buffer(Buffer&& other) noexcept : data(other.data) { other.data = nullptr; } Buffer& operator=(Buffer&& other) noexcept { if (&other != this) { delete[] data; data = other.data; other.data = nullptr; } return *this; } };
Bir sınıf bir işaretçiyi yönetiyorsa sadece yıkıcıyı uygulamak yeterli midir?
Hayır. Kopyalama ve taşıma işlemleri olmadan kopyalandığında çift serbest bırakma meydana gelir. Örneğin:
Buffer a(10); Buffer b = a; // b ve a aynı işaretçiyi silecek!
Hikaye
Telekomünikasyon veri toplama platformunda tüm sınıflar sadece yıkıcıyı tanımlıyordu. Yapıların yeniden düzenlenmesinden sonra toplu çift serbest bırakma hatası yaşandı: nesnelerin kopyalanması rastgele davranışlar sergiledi.
Hikaye
Mobil oyun projesinde, bir konteyner sınıfı için taşıma yapıcısı uygulamayı unuttular. Taşınma sırasında nesne kopyalandı, bu da fazladan veri kopyalama ve performans düşüşüne neden oldu.
Hikaye
Veri yapılarının serileştirilmesi kütüphanesinde, bir fonksiyondan nesne dönerken geçici bir nesne döndürülüyordu ve kopyalama yapıcısı işaretçinin yüzeysel kopyasını yapıyordu. Birçok bellek sızıntısı meydana geldi ve bu, yalnızca aylarca çalıştıktan sonra ortaya çıktı.