Apa perbedaan antara salinan dalam dan salinan dangkal?
language-agnostic
copy
deep-copy
shallow-copy
David Locke
sumber
sumber
Jawaban:
Salinan dangkal duplikat sesedikit mungkin. Salinan dangkal koleksi adalah salinan struktur koleksi, bukan elemen. Dengan salinan dangkal, dua koleksi sekarang berbagi elemen individu.
Salinan yang dalam menggandakan semuanya. Salinan dalam koleksi adalah dua koleksi dengan semua elemen dalam koleksi asli digandakan.
sumber
Luasnya vs Kedalaman; berpikir dalam hal pohon referensi dengan objek Anda sebagai simpul root.
Dangkal:
Variabel A dan B merujuk ke area memori yang berbeda, ketika B ditugaskan ke A, kedua variabel merujuk ke area memori yang sama. Kemudian modifikasi pada konten keduanya langsung tercermin dalam konten lainnya, karena mereka berbagi konten.
Dalam:
Variabel A dan B merujuk ke area memori yang berbeda, ketika B ditugaskan ke A nilai-nilai di area memori yang A menunjuk ke disalin ke area memori yang B menunjuk. Kemudian modifikasi pada konten keduanya tetap unik untuk A atau B; isinya tidak dibagikan.
sumber
Singkatnya, itu tergantung pada poin apa. Dalam salinan dangkal, objek B menunjuk ke lokasi objek A di memori. Dalam penyalinan dalam, semua hal di lokasi memori objek A disalin ke lokasi memori objek B.
Artikel wiki ini memiliki diagram yang bagus.
http://en.wikipedia.org/wiki/Object_copy
sumber
Coba pertimbangkan gambar berikut
Misalnya Object.MemberwiseClone membuat salinan dangkal tautan
dan menggunakan antarmuka ICloneable Anda bisa mendapatkan salinan dalam seperti yang dijelaskan di sini
sumber
Khusus Untuk Pengembang iOS:
Jika
B
adalah salinan dangkal dariA
, maka untuk data primitif itu sepertiB = [A assign];
dan untuk benda-benda itu sepertiB = [A retain]
;B dan A menunjuk ke lokasi memori yang sama
Jika
B
adalah copy dalam dariA
, maka itu sepertiB = [A copy];
B dan A menunjuk ke lokasi memori yang berbeda
Alamat memori B sama dengan A
B memiliki konten yang sama dengan A
sumber
Salinan dangkal: Menyalin nilai anggota dari satu objek ke objek lainnya.
Salinan Jauh: Menyalin nilai anggota dari satu objek ke objek lainnya.
Setiap objek pointer digandakan dan Disalin Dalam.
Contoh:
sumber
Saya belum melihat jawaban yang singkat dan mudah dipahami di sini - jadi saya akan mencobanya.
Dengan salinan dangkal, objek apa pun yang ditunjukkan oleh sumber juga ditunjukkan oleh tujuan (sehingga tidak ada objek yang direferensikan disalin).
Dengan salinan yang dalam, objek apa pun yang ditunjuk oleh sumber akan disalin dan salinannya diarahkan ke tujuan (jadi sekarang akan ada 2 dari setiap objek yang direferensikan). Ini berulang ke pohon objek.
sumber
Hanya demi pemahaman yang mudah, Anda dapat mengikuti artikel ini: https://www.cs.utexas.edu/~scottm/cs307/handouts/deepCopying.htm
Salinan dangkal:
Salinan Dalam:
sumber
{Bayangkan dua objek: A dan B dengan jenis yang sama _t (sehubungan dengan C ++) dan Anda berpikir tentang penyalinan dangkal / dalam A ke B}
Salinan Dangkal: Cukup buat salinan referensi ke A ke B. Pikirkan sebagai salinan Alamat A. Jadi, alamat A dan B akan sama yaitu mereka akan menunjuk ke lokasi memori yang sama yaitu isi data.
Salinan dalam: Cukup buat salinan dari semua anggota A, alokasikan memori di lokasi yang berbeda untuk B dan kemudian tetapkan anggota yang disalin ke B untuk mendapatkan salinan yang dalam. Dengan cara ini, jika A menjadi tidak ada, B masih valid dalam memori. Istilah yang benar untuk digunakan adalah kloning, di mana Anda tahu bahwa keduanya sama, tetapi berbeda (yaitu disimpan sebagai dua entitas yang berbeda dalam ruang memori). Anda juga dapat memberikan pembungkus klon di mana Anda dapat memutuskan melalui daftar inklusi / pengecualian properti mana yang akan dipilih selama penyalinan dalam. Ini adalah praktik yang cukup umum ketika Anda membuat API.
Anda dapat memilih untuk melakukan Salinan Dangkal ONLY_IF Anda memahami taruhannya. Ketika Anda memiliki sejumlah besar pointer untuk berurusan dengan C ++ atau C, melakukan salinan objek yang dangkal benar - benar ide yang buruk.
EXAMPLE_OF_DEEP COPY_ Contohnya adalah, ketika Anda mencoba melakukan pemrosesan gambar dan pengenalan objek, Anda perlu menutupi "Gerakan Tidak Relevan dan Berulang-ulang" dari area pemrosesan Anda. Jika Anda menggunakan penunjuk gambar, maka Anda mungkin memiliki spesifikasi untuk menyimpan gambar topeng itu. SEKARANG ... jika Anda melakukan salinan gambar yang dangkal, ketika referensi pointer DIBUNUH dari tumpukan, Anda kehilangan referensi dan salinannya yaitu akan ada kesalahan runtime pelanggaran akses di beberapa titik. Dalam hal ini, yang Anda butuhkan adalah salinan gambar Anda yang dalam dengan mengkloningnya. Dengan cara ini Anda dapat mengambil topeng jika Anda membutuhkannya di masa depan.
EXAMPLE_OF_SHALLOW_COPY Saya tidak terlalu berpengetahuan dibandingkan dengan pengguna di StackOverflow jadi jangan ragu untuk menghapus bagian ini dan memberikan contoh yang baik jika Anda bisa mengklarifikasi. Tapi saya benar-benar berpikir itu bukan ide yang baik untuk melakukan copy dangkal jika Anda tahu bahwa program Anda akan berjalan untuk waktu yang tak terbatas yaitu operasi "push-pop" terus menerus selama stack dengan panggilan fungsi. Jika Anda mendemonstrasikan sesuatu kepada orang amatir atau pemula (mis. C / C ++ tutorial stuff) maka mungkin tidak apa-apa. Tetapi jika Anda menjalankan aplikasi seperti sistem pengawasan dan deteksi, atau Sistem Pelacakan Sonar, Anda tidak seharusnya terus menyalin objek Anda dengan dangkal karena itu akan membunuh program Anda cepat atau lambat.
sumber
'ShallowCopy' menunjuk ke lokasi yang sama dalam memori seperti 'Sumber'. 'DeepCopy' menunjuk ke lokasi yang berbeda dalam memori, tetapi isinya sama.
sumber
Apa itu Salinan Dangkal?
Salinan dangkal adalah salinan objek yang sedikit bijaksana. Objek baru dibuat yang memiliki salinan tepat dari nilai-nilai di objek asli. Jika salah satu bidang objek referensi ke objek lain, hanya alamat referensi yang disalin yaitu, hanya alamat memori yang disalin.
Dalam gambar ini,
MainObject1
memiliki bidangfield1
tipe int, danContainObject1
tipeContainObject
. Ketika Anda melakukan salinan dangkalMainObject1
,MainObject2
dibuat denganfield2
berisi nilai yang disalinfield1
dan masih menunjuk keContainObject1
dirinya sendiri. Perhatikan bahwa karenafield1
ini adalah tipe primitif, nilainya disalinfield2
tetapi karenaContainedObject1
merupakan objek,MainObject2
masih menunjuk keContainObject1
. Jadi setiap perubahan yang dilakukanContainObject1
padaMainObject1
akan tercermin dalamMainObject2
.Sekarang jika ini adalah salinan dangkal, mari kita lihat apa yang ada di dalamnya?
Apa itu Deep Copy?
Salinan yang dalam menyalin semua bidang, dan membuat salinan dari memori yang dialokasikan secara dinamis ditunjuk oleh bidang tersebut. Salinan dalam terjadi ketika suatu objek disalin bersama dengan objek yang dirujuk.
Dalam gambar ini, MainObject1 memiliki bidang
field1
tipe int, danContainObject1
tipeContainObject
. Ketika Anda melakukan salinan dalamMainObject1
,MainObject2
dibuat denganfield2
berisi nilai yang disalinfield1
danContainObject2
mengandung nilai yang disalinContainObject1
. Perhatikan bahwa perubahan apa pun yang dilakukanContainObject1
padaMainObject1
tidak akan mencerminkanMainObject2
.artikel bagus
sumber
field3
yang ketika dalam posisi mencoba dan memahami sesuatu sedalam masalah itu, di mana # 3 dalam contoh itu terjadiContainObject2
?Dalam pemrograman berorientasi objek, tipe menyertakan kumpulan bidang anggota. Bidang-bidang ini dapat disimpan dengan nilai atau referensi (yaitu, penunjuk ke nilai).
Dalam salinan dangkal, instance baru dari tipe dibuat dan nilai-nilai disalin ke instance baru. Pointer referensi juga disalin seperti nilainya. Oleh karena itu, referensi menunjuk ke objek aslinya. Setiap perubahan pada anggota yang disimpan dengan referensi muncul di dokumen asli dan salinan, karena tidak ada salinan yang dibuat dari objek yang direferensikan.
Dalam salinan yang dalam, bidang yang disimpan oleh nilai disalin seperti sebelumnya, tetapi pointer ke objek yang disimpan oleh referensi tidak disalin. Sebagai gantinya, salinan yang dalam dibuat dari objek yang direferensikan, dan sebuah pointer ke objek baru disimpan. Setiap perubahan yang dilakukan pada objek yang direferensikan tidak akan mempengaruhi salinan objek lainnya.
sumber
'ShallowCopy' menunjuk ke lokasi yang sama dalam memori seperti 'Sumber'. 'DeepCopy' menunjuk ke lokasi yang berbeda dalam memori, tetapi isinya sama.
sumber
Kloning Dangkal:
Definisi: "Salinan dangkal suatu objek menyalin objek 'utama', tetapi tidak menyalin objek dalam." Ketika objek kustom (mis. Karyawan) baru saja primitif, variabel tipe String maka Anda menggunakan Kloning Dangkal.
Anda kembali
super.clone();
dengan metode clone () yang ditimpa dan pekerjaan Anda selesai.Kloning Dalam :
Definisi: "Berbeda dengan salinan yang dangkal, salinan yang dalam adalah salinan yang sepenuhnya independen dari suatu objek."
Berarti ketika objek Karyawan memegang objek kustom lain:
Maka Anda harus menulis kode untuk mengkloning objek 'Alamat' juga dalam metode clone () yang diganti. Jika tidak, objek Alamat tidak akan dikloning dan menyebabkan bug ketika Anda mengubah nilai Alamat di objek Karyawan yang dikloning, yang mencerminkan yang asli juga.
sumber
sumber
Salinan Yang Dalam
Salinan yang dalam menyalin semua bidang, dan membuat salinan dari memori yang dialokasikan secara dinamis ditunjuk oleh bidang tersebut. Salinan dalam terjadi ketika suatu objek disalin bersama dengan objek yang dirujuk.
Salinan dangkal
Salinan dangkal adalah salinan objek yang sedikit bijaksana. Objek baru dibuat yang memiliki salinan tepat dari nilai-nilai di objek asli. Jika salah satu bidang objek referensi ke objek lain, hanya alamat referensi yang disalin yaitu, hanya alamat memori yang disalin.
sumber
Salinan Dangkal - Variabel referensi di dalam objek asli dan disalin dangkal memiliki referensi ke objek umum .
Salinan Jauh - Variabel referensi di dalam objek asli dan yang disalin memiliki referensi ke objek yang berbeda .
kelas utama mengikuti-
OutPut di atas akan menjadi-
Setiap perubahan yang dilakukan pada objek asli akan mencerminkan objek dangkal tidak dalam objek yang mendalam.
OutPut- ViSuaLBaSiC C
sumber
Saya ingin memberi contoh daripada definisi formal.
Kode ini menunjukkan salinan dangkal :
Kode ini menunjukkan salinan dalam :
sumber
1 1 4 4 4 4 4 4
sumber
Dalam Ketentuan Sederhana, Salinan Dangkal mirip dengan Call By Reference dan Deep Copy mirip dengan Call By Value
Dalam Call By Reference, parameter formal dan aktual dari suatu fungsi merujuk ke lokasi memori yang sama dan nilainya.
Dalam Nilai Panggilan Menurut, parameter formal dan aktual dari suatu fungsi merujuk ke lokasi memori yang berbeda tetapi memiliki nilai yang sama.
sumber
Bayangkan ada dua array yang disebut arr1 dan arr2.
sumber
Salinan dangkal membangun objek majemuk baru dan memasukkan referensi ke dalamnya ke objek asli.
Tidak seperti salinan dangkal, deepcopy membangun objek senyawa baru dan juga menyisipkan salinan objek asli objek senyawa asli.
Mari kita ambil contoh.
Kode di atas mencetak SALAH.
Coba lihat caranya.
Objek majemuk asli
x=[1,[2]]
(disebut senyawa karena memiliki objek di dalam objek (Inception))seperti yang Anda lihat pada gambar, ada daftar di dalam daftar.
Lalu kami membuat salinan dangkal menggunakan
y = copy.copy(x)
. Apa yang python lakukan di sini adalah, ia akan membuat objek majemuk baru tetapi objek di dalamnya menunjuk ke objek orignal.Dalam gambar itu telah membuat salinan baru untuk daftar luar. tetapi daftar bagian dalam tetap sama dengan yang asli.
Sekarang kami membuat deepcopy menggunakan itu
z = copy.deepcopy(x)
. apa yang python lakukan di sini adalah, itu akan membuat objek baru untuk daftar luar maupun daftar dalam. seperti yang ditunjukkan pada gambar di bawah (disorot merah).Pada kode akhir dicetak
False
, karena y dan z bukan objek yang sama.HTH.
sumber
Salinan dangkal adalah membuat objek baru dan kemudian menyalin bidang non-statis objek saat ini ke objek baru. Jika bidang adalah tipe nilai -> salinan bidang sedikit demi sedikit dilakukan; untuk tipe referensi -> referensi disalin tetapi objek yang dirujuk tidak; Oleh karena itu objek asli dan klonnya merujuk pada objek yang sama.
Dalam copy adalah menciptakan objek baru dan kemudian menyalin bidang nonstatic dari objek saat ini ke objek baru. Jika bidang adalah tipe nilai -> salinan bidang sedikit demi sedikit dilakukan. Jika bidang adalah tipe referensi -> salinan baru dari objek yang dirujuk dilakukan. Kelas yang akan dikloning harus ditandai sebagai [Serializable].
sumber
Diambil dari [blog]: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html
Salinan mendalam melibatkan penggunaan konten dari satu objek untuk membuat instance lain dari kelas yang sama. Dalam salinan yang dalam, kedua objek mungkin berisi informasi yang sama tetapi objek target akan memiliki buffer dan sumber dayanya sendiri. penghancuran salah satu objek tidak akan mempengaruhi objek yang tersisa. Operator tugas yang kelebihan beban akan membuat salinan objek yang dalam.
Salinan dangkal melibatkan menyalin konten dari satu objek ke instance lain dari kelas yang sama sehingga menciptakan gambar cermin. Karena penyalinan langsung referensi dan petunjuk, kedua objek akan berbagi konten yang sama secara eksternal dari objek lain menjadi tidak dapat diprediksi.
Penjelasan:
Menggunakan copy constructor kami cukup menyalin nilai data anggota dengan anggota. Metode penyalinan ini disebut salinan dangkal. Jika objek adalah kelas sederhana, terdiri dari tipe bawaan dan tidak ada pointer ini akan diterima. Fungsi ini akan menggunakan nilai-nilai dan objek-objek dan perilakunya tidak akan diubah dengan salinan dangkal, hanya alamat pointer yang anggota disalin dan bukan nilai alamat yang menunjuk. Nilai data objek kemudian akan secara tidak sengaja diubah oleh fungsi. Ketika fungsi keluar dari ruang lingkup, salinan objek dengan semua datanya muncul dari tumpukan.
Jika objek memiliki pointer, salinan yang dalam perlu dieksekusi. Dengan salinan mendalam dari suatu objek, memori dialokasikan untuk objek di toko bebas dan elemen yang ditunjuk untuk disalin. Salinan dalam digunakan untuk objek yang dikembalikan dari suatu fungsi.
sumber
Untuk menambahkan lebih banyak ke jawaban lain,
sumber
Salinan dangkal tidak akan membuat referensi baru tetapi salinan yang dalam akan membuat referensi baru.
Berikut adalah program untuk menjelaskan salinan yang dalam dan dangkal.
sumber
Salinan salinan:
Array adalah kelas, yang artinya adalah tipe referensi sehingga array1 = array2 menghasilkan dua variabel yang mereferensikan array yang sama.
Tapi lihat contoh ini:
clone dangkal berarti bahwa hanya memori yang diwakili oleh array yang dikloning disalin.
Jika array berisi objek tipe nilai, nilai disalin ;
jika array berisi tipe referensi, hanya referensi yang disalin - sehingga ada dua array yang anggotanya mereferensikan objek yang sama .
Untuk membuat salinan yang dalam — di mana tipe referensi digandakan, Anda harus mengulang array dan mengkloning setiap elemen secara manual.
sumber
private void button1_Click(object sender, EventArgs e) { int[] arr1 = new int[]{1,2,3,4,5}; int[] arr2 = new int[]{6,7,8,9,0}; MessageBox.Show(arr1[2] + " " + arr2[2]); arr2 = arr1; MessageBox.Show(arr1[2] + " " + arr2[2]); arr1[2] = 12; MessageBox.Show(arr1[2] + " " + arr2[2]); }
Saya jadi mengerti dari baris-baris berikut.
Salinan dangkal menyalin bidang tipe nilai objek (int, float, bool) ke objek target dan tipe referensi objek (string, kelas dll) disalin sebagai referensi di objek target. Dalam target referensi ini jenis akan menunjuk ke lokasi memori objek sumber.
Salinan yang dalam menyalin nilai objek dan tipe referensi ke dalam salinan objek objek yang lengkap yang baru. Ini berarti tipe nilai dan tipe referensi akan dialokasikan ke lokasi memori baru.
sumber
Menambahkan ke semua definisi di atas, satu salinan dalam yang lebih dan paling sering digunakan, ada di copy constructor (atau overloading assignment oprator) dari kelas.
Salinan dangkal -> adalah saat Anda tidak menyediakan pembuat salinan. Di sini, hanya objek yang disalin tetapi tidak semua anggota kelas disalin.
Salinan dalam -> adalah ketika Anda telah memutuskan untuk mengimplementasikan copy constructor atau tugas yang berlebihan di kelas Anda dan memungkinkan menyalin semua anggota kelas.
sumber
Copy constructor digunakan untuk menginisialisasi objek baru dengan objek yang dibuat sebelumnya dari kelas yang sama. Secara default kompiler menulis salinan yang dangkal. Salinan dangkal berfungsi dengan baik ketika alokasi memori dinamis tidak terlibat karena ketika alokasi memori dinamis terlibat maka kedua objek akan menunjuk ke lokasi memori yang sama di tumpukan, Oleh karena itu untuk menghapus masalah ini kami menulis salinan yang dalam sehingga kedua objek memiliki salinan atributnya sendiri dalam memori. Untuk membaca detail dengan contoh dan penjelasan lengkap, Anda bisa melihat artikel C ++ konstruktor .
sumber