Kopya yapıcı ve kopya atama operatörü, kaynaklara (örneğin, dinamik belleğe) sahip nesnelerle çalışmak için gereklidir. Varsayılan olarak, derleyici alan alan kopyası oluşturur ki bu ham gösterici için güvenli değildir:
class Buffer { public: Buffer(size_t size) { data = new int[size]; this->size = size; } ~Buffer() { delete[] data; } // Kopya yapıcının doğru uygulanması Buffer(const Buffer& other) : size(other.size) { data = new int[size]; std::copy(other.data, other.data + size, data); } // Doğru atama operatörü Buffer& operator=(const Buffer& other) { if (this != &other) { delete[] data; size = other.size; data = new int[size]; std::copy(other.data, other.data + size, data); } return *this; } private: int* data; size_t size; };
Aksi takdirde, iki nesne kopyalandığında biri belleği serbest bırakır, diğeri sarkan bir gösterici ile kalır (çift serbest bırakma veya serbest bırakmadan sonra kullanım).
Sadece kopya yapıcı açıkça tanımlanırsa, atama operatörü ne olur? Ne zaman gerekir, ne zaman gerekmez?
Cevap: Eğer sadece kopya yapıcı tanımlanmış ancak atama operatörü tanımlanmamışsa, derleyici varsayılan atama operatörünü (bit bazında kopyalama) oluşturur, bu da dinamik kaynaklara sahip bir nesne için tehlikeli olacaktır; yani aynı göstericiyi iki kez serbest bırakacaktır.
Bellek yönetimi durumunda her ikisini de uygulamak gerekir: hem kopya yapıcıyı hem de atama operatörünü, kopyalama/hafıza sızıntısı hatalarından kaçınmak için.
Hikaye
Bir medya sunucusunda, bir buffer nesnesinin kopyalanmasında kopya yapıcı kullanıldı, ancak atama operatörü unutuldu. Bir buffer diğerine atanırken, nesnelerin yok edilmesinde çift bellek serbest bırakma meydana geldi. Hata stres testlerinde ortaya çıktı.
Hikaye
Taşıma lojistiği projesinde varsayılan atama operatörü, koordinat dizisine işaret eden bir yapıyı kopyaladı. Bir nesne silindikten sonra diğeri serbest bırakılmış belleğe erişerek segmentasyon hataları oluşturuyordu.
Hikaye
Grafik kaynaklarla ilgili bir projede, nesnelerin akışlar arasında iletilmesinde kopya yapıcının uygulanması unutuldu. Değer ile iletildiğinde, yüzeysel kopyalama meydana geldi ve diğer akıştaki nesne değiştirildiğinde veri bozulması ve programın çökmesi gerçekleşti.