Shallow copy (yüzeysel kopyalama) yalnızca sınıfın üye değerlerini, işaretçileri dahil olmak üzere kopyalar — ancak bu işaretçilerin işaret ettiği verilere kopyalamaz. Deep copy (derin kopyalama) işaretçiler tarafından gösterilen verilerin yeni kopyalarını oluşturur, bu da bellek paylaşımını ve çift serbest bırakmayı önler.
Örnek:
class Buffer { public: Buffer(size_t size) : size(size), data(new int[size]) {} // Shallow copy (yanlış) Buffer(const Buffer& other) : size(other.size), data(other.data) {} // Deep copy (doğru) 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; } ~Buffer() { delete[] data; } private: size_t size; int* data; };
Sınıf dinamik bir diziye işaretçi içeriyorsa, neden varsayılan kopya yapıcı ve operator= 'yi kopyalayıp yapıştırmak yeterli değildir?
Doğru cevap:
Varsayılan kopyalama yüzeysel kopyalamayı gerçekleştirir. İki nesne aynı diziye işaret eder ve yok edilmesi sırasında aynı bellek alanını iki kez serbest bırakma girişiminde bulunulursa (çift serbest bırakma), bu bir çöküşe neden olur.
Hikaye Büyük bir sunucu uygulamasında, pikselin dinamik belleğini yöneten özel bir Image sınıfı uygulanmıştı. Geliştiriciler derin kopyalamayı uygulamamıştı ve Image nesnelerinin bir değer olarak iletilmesi sırasında bellek çift serbest bırakmaya neden oldu ve bu da birkaç günde bir çöküşlere yol açtı.
Hikaye Bir öğrenci projesinde, dinamik olarak tahsis edilen hücre dizisine işaret eden bir Field kapsayıcısı kullanıldı. Dizi boyutu değiştirildiğinde kopyalama yapıcı yalnızca işaretçiyi kopyaladı ve her iki kapsayıcı da aynı bellek alanıyla çalıştı, bu da tutarsız verilere ve zor bulunur hatalara neden oldu.
Hikaye Eski C++ kodunda, bir grafik motoru için Texture sınıfı, kendi yok edicisi ve atama operatörü olmadan uygulanmıştı, bu da kopyalama ve geçici doku nesnelerinin atanması sırasında bellek sızıntılarına neden oldu.