Jaka jest różnica między kopią głęboką a płytką?
language-agnostic
copy
deep-copy
shallow-copy
David Locke
źródło
źródło
Odpowiedzi:
Płytkie kopie powielają jak najmniej. Płytka kopia kolekcji jest kopią struktury kolekcji, a nie elementów. Dzięki płytkiej kopii dwie kolekcje dzielą teraz poszczególne elementy.
Głębokie kopie duplikują wszystko. Głęboka kopia kolekcji to dwie kolekcje ze zduplikowanymi wszystkimi elementami oryginalnej kolekcji.
źródło
Szerokość vs głębokość; myśl w kategoriach drzewa odniesień z twoim obiektem jako węzłem głównym.
Płycizna:
Zmienne A i B odnoszą się do różnych obszarów pamięci, gdy B jest przypisane do A, dwie zmienne odnoszą się do tego samego obszaru pamięci. Późniejsze modyfikacje zawartości jednego z nich są natychmiast odzwierciedlane w treści innych, ponieważ udostępniają zawartość.
Głęboki:
Zmienne A i B odnoszą się do różnych obszarów pamięci, gdy B jest przypisane do A, wartości w obszarze pamięci, na które wskazuje A, są kopiowane do obszaru pamięci, na który wskazuje B. Późniejsze modyfikacje zawartości albo pozostają unikalne dla A lub B; zawartość nie jest udostępniana.
źródło
Krótko mówiąc, zależy to od tego, co wskazuje na co. W płytkiej kopii obiekt B wskazuje lokalizację obiektu A w pamięci. W głębokiej kopii wszystkie rzeczy w lokalizacji pamięci obiektu A są kopiowane do lokalizacji pamięci obiektu B.
Ten artykuł wiki ma świetny schemat.
http://en.wikipedia.org/wiki/Object_copy
źródło
Spróbuj rozważyć następujący obraz
Na przykład Object.MemberwiseClone tworzy płytkie łącze do kopiowania
i za pomocą interfejsu ICloneable możesz uzyskać głęboką kopię, jak opisano tutaj
źródło
Specjalnie dla programistów iOS:
Jeśli
B
jest to płytkie kopia zA
, a następnie do pierwotnych danych to jakB = [A assign];
i dla obiektów to jakB = [A retain]
;B i A wskazują na to samo miejsce w pamięci
Jeśli
B
jest głęboka kopia zA
, to jest jakB = [A copy];
B i A wskazują różne lokalizacje pamięci
Adres pamięci B jest taki sam jak adresu A.
B ma taką samą zawartość jak A
źródło
Płytka kopia: Kopiuje wartości składowe z jednego obiektu do drugiego.
Głębokie kopiowanie: Kopiuje wartości składowe z jednego obiektu do drugiego.
Wszelkie obiekty wskaźnika są powielane i głęboko kopiowane.
Przykład:
źródło
Nie widziałem tutaj krótkiej, łatwej do zrozumienia odpowiedzi - spróbuję.
W przypadku płytkiej kopii każdy obiekt wskazywany przez źródło jest również wskazywany przez miejsce docelowe (tak, aby żadne obiekty odniesienia nie były kopiowane).
W przypadku głębokiej kopii każdy obiekt wskazywany przez źródło jest kopiowany, a kopia jest wskazywana przez miejsce docelowe (więc będą teraz 2 każdego obiektu odniesienia). Powtarza się w dół drzewa obiektów.
źródło
Aby ułatwić zrozumienie, możesz śledzić ten artykuł: https://www.cs.utexas.edu/~scottm/cs307/handouts/deepCopying.htm
Płytka kopia:
Głęboka kopia:
źródło
{Wyobraź sobie dwa obiekty: A i B tego samego typu _t (w odniesieniu do C ++) i myślisz o płytkim / głębokim kopiowaniu A do B}
Płytka kopia: po prostu tworzy kopię odwołania do A w B. Pomyśl o tym jak o kopii adresu A. Tak więc adresy A i B będą takie same, tzn. Będą wskazywać tę samą lokalizację pamięci, tj. Zawartość danych.
Głęboka kopia: po prostu tworzy kopię wszystkich członków A, przydziela pamięć w innym miejscu dla B, a następnie przypisuje skopiowane elementy do B w celu uzyskania głębokiej kopii. W ten sposób, jeśli A stanie się nieistniejące, B jest nadal ważne w pamięci. Prawidłowym terminem byłoby klonowanie, jeśli wiesz, że oba są całkowicie takie same, ale jednak różne (tj. Przechowywane jako dwie różne jednostki w przestrzeni pamięci). Możesz także podać swoje opakowanie klonu, w którym możesz zdecydować za pomocą listy włączenia / wyłączenia, które właściwości wybrać podczas głębokiego kopiowania. Jest to dość powszechna praktyka podczas tworzenia interfejsów API.
Możesz wykonać płytką kopię TYLKO_Jeśli rozumiesz związane z nią stawki. Kiedy masz ogromną liczbę wskaźników, którymi trzeba się posługiwać w C ++ lub C, robienie płytkiej kopii obiektu jest NAPRAWDĘ złym pomysłem.
PRZYKŁAD_OF_DEEP KOPIA_ Przykładem jest, gdy próbujesz wykonać przetwarzanie obrazu i rozpoznawanie obiektu, musisz zamaskować „Nieistotny i powtarzalny ruch” poza obszarami przetwarzania. Jeśli korzystasz ze wskaźników obrazu, możesz mieć specyfikację zapisywania obrazów maski. TERAZ ... jeśli zrobisz płytką kopię obrazu, gdy referencje wskaźnika zostaną ZABIJANE ze stosu, utracisz referencję i jej kopię, tzn. W pewnym momencie wystąpi błąd w czasie wykonywania naruszenia dostępu. W takim przypadku potrzebujesz głębokiej kopii obrazu, KLONUJĄC go. W ten sposób możesz odzyskać maski na wypadek, gdyby były potrzebne w przyszłości.
EXAMPLE_OF_SHALLOW_COPY Nie jestem bardzo kompetentny w porównaniu do użytkowników w StackOverflow, więc możesz usunąć tę część i dać dobry przykład, jeśli możesz to wyjaśnić. Ale naprawdę uważam, że nie jest dobrym pomysłem wykonywanie płytkich kopii, jeśli wiesz, że twój program będzie działał przez nieskończony okres czasu, tj. Ciągła operacja „push-pop” na stosie z wywołaniami funkcji. Jeśli demonstrujesz coś amatorowi lub nowicjuszowi (np. Samouczki C / C ++), prawdopodobnie jest to w porządku. Ale jeśli korzystasz z aplikacji, takiej jak system nadzoru i wykrywania lub Sonar Tracking System, nie powinieneś ciągle kopiować swoich obiektów, ponieważ prędzej czy później zabije Twój program.
źródło
„ShallowCopy” wskazuje to samo miejsce w pamięci, co „Source”. „DeepCopy” wskazuje na inną lokalizację w pamięci, ale zawartość jest taka sama.
źródło
Co to jest Shallow Copy?
Płytka kopia to nieco mądra kopia obiektu. Tworzony jest nowy obiekt, który ma dokładną kopię wartości w oryginalnym obiekcie. Jeśli którekolwiek z pól obiektu są odwołaniami do innych obiektów, kopiowane są tylko adresy referencyjne, tzn. Kopiowany jest tylko adres pamięci.
Na tym rysunku
MainObject1
ma polafield1
typu int iContainObject1
typuContainObject
. Kiedy zrobisz płytką kopięMainObject1
,MainObject2
tworzony jest zfield2
zawartością skopiowanej wartościfield1
i nadal wskazuje naContainObject1
siebie. Zauważ, że skorofield1
jest typu pierwotnego, jego wartość jest kopiowana,field2
ale ponieważContainedObject1
jest obiektem,MainObject2
nadal wskazujeContainObject1
. Tak więc wszelkie zmiany wprowadzoneContainObject1
wMainObject1
zostaną odzwierciedlone wMainObject2
.Teraz, jeśli jest to płytka kopia, zobaczmy, co to jest głęboka kopia?
Co to jest Deep Copy?
Głęboka kopia kopiuje wszystkie pola i tworzy kopie dynamicznie alokowanej pamięci wskazanej przez pola. Głęboka kopia występuje, gdy obiekt jest kopiowany wraz z obiektami, do których się odnosi.
Na tym rysunku obiekt MainObject1 ma pola
field1
typu int iContainObject1
typuContainObject
. Po wykonaniu głębokiej kopiiMainObject1
,MainObject2
jest tworzony zfield2
zawartością skopiowanej wartościfield1
iContainObject2
z wartością skopiowanej wartościContainObject1
. Uwaga: wszelkie zmiany wprowadzone wContainObject1
wMainObject1
nie będą odzwierciedlone wMainObject2
.dobry artykuł
źródło
field3
której, gdy jesteś w stanie spróbować zrozumieć coś tak głębokiego jak ten problem, gdzie jest to, że # 3 w tym przykładzie ma miejsceContainObject2
?W programowaniu obiektowym typ zawiera zbiór pól składowych. Te pola mogą być przechowywane albo według wartości, albo przez odniesienie (tj. Wskaźnik do wartości).
W płytkiej kopii tworzona jest nowa instancja tego typu, a wartości są kopiowane do nowej instancji. Wskaźniki odniesienia są również kopiowane tak jak wartości. Dlatego odniesienia odnoszą się do oryginalnych obiektów. Wszelkie zmiany elementów składowych, które są przechowywane przez odniesienie, pojawiają się zarówno w oryginale, jak i kopii, ponieważ nie wykonano żadnej kopii obiektu odniesienia.
W głębokiej kopii pola przechowywane według wartości są kopiowane jak poprzednio, ale wskaźniki do obiektów przechowywanych przez odniesienie nie są kopiowane. Zamiast tego tworzona jest głęboka kopia obiektu, do którego istnieje odniesienie, i zapisywany jest wskaźnik do nowego obiektu. Wszelkie zmiany wprowadzone do tych obiektów, do których istnieją odniesienia, nie wpłyną na inne kopie obiektu.
źródło
„ShallowCopy” wskazuje to samo miejsce w pamięci, co „Source”. „DeepCopy” wskazuje na inną lokalizację w pamięci, ale zawartość jest taka sama.
źródło
Płytkie klonowanie:
definicja: „ Płytka kopia obiektu kopiuje obiekt„ główny ”, ale nie kopiuje obiektów wewnętrznych.” Kiedy obiekt niestandardowy (np. Pracownik) ma po prostu prymitywne, zmienne typu String, wówczas używasz Shallow Cloning.
Wracasz
super.clone();
w zastąpionej metodzie clone () i twoje zadanie się kończy.Głębokie klonowanie :
definicja: „W przeciwieństwie do płytkiej kopii, głęboka kopia jest w pełni niezależną kopią obiektu”.
Oznacza, że obiekt pracownika zawiera inny obiekt niestandardowy:
Następnie musisz napisać kod, aby sklonować obiekt „Adres” również w przesłoniętej metodzie clone (). W przeciwnym razie obiekt Adres nie zostanie sklonowany i spowoduje błąd, gdy zmienisz wartość Adres w sklonowanym obiekcie pracownika, co również odzwierciedla pierwotny.
źródło
źródło
Deep Copy
Głęboka kopia kopiuje wszystkie pola i tworzy kopie dynamicznie alokowanej pamięci wskazanej przez pola. Głęboka kopia występuje, gdy obiekt jest kopiowany wraz z obiektami, do których się odnosi.
Płytka kopia
Płytka kopia to nieco mądra kopia obiektu. Tworzony jest nowy obiekt, który ma dokładną kopię wartości w oryginalnym obiekcie. Jeśli którekolwiek z pól obiektu są odwołaniami do innych obiektów, kopiowane są tylko adresy referencyjne, tzn. Kopiowany jest tylko adres pamięci.
źródło
Płytka kopia - zmienna odniesienia wewnątrz oryginalnych i płytko skopiowanych obiektów ma odniesienie do wspólnego obiektu.
Głębokie kopiowanie - zmienna odniesienia w oryginalnych i głęboko skopiowanych obiektach ma odniesienie do innego obiektu.
główna klasa jest następująca-
OutPut powyżej będzie-
Wszelkie zmiany dokonane w obiekcie pierwotnym będą odzwierciedlone w obiekcie płytkim, a nie w obiekcie głębokim.
OutPut- ViSuaLBaSiC C
źródło
Chciałbym podać przykład zamiast formalnej definicji.
Ten kod pokazuje płytką kopię :
Ten kod pokazuje głęboką kopię :
źródło
1 1 4 4 4 4 4 4
źródło
Mówiąc najprościej, płytka kopia jest podobna do funkcji Call by Reference, a głęboka kopia jest podobna do funkcji Call by Value
W Call By Reference zarówno formalne, jak i rzeczywiste parametry funkcji odnoszą się do tej samej lokalizacji w pamięci i wartości.
W Call By Value zarówno formalne, jak i rzeczywiste parametry funkcji odnoszą się do innej lokalizacji pamięci, ale mają tę samą wartość.
źródło
Wyobraź sobie, że istnieją dwie tablice zwane arr1 i arr2.
źródło
Płytka kopia konstruuje nowy obiekt złożony i wstawia do niego swoje odniesienia do oryginalnego obiektu.
W przeciwieństwie do płytkiej kopii, kopiowanie głębokie konstruuje nowy obiekt złożony, a także wstawia kopie oryginalnych obiektów oryginalnego obiektu złożonego.
Weźmy przykład.
Powyższy kod drukuje FAŁSZ.
Zobaczmy jak.
Oryginalny obiekt złożony
x=[1,[2]]
(nazywany jako obiekt złożony, ponieważ ma obiekt wewnątrz obiektu (Inception))jak widać na obrazku, wewnątrz listy znajduje się lista.
Następnie tworzymy jego płytką kopię za pomocą
y = copy.copy(x)
. To, co robi tutaj Python, spowoduje utworzenie nowego obiektu złożonego, ale obiekty wewnątrz niego wskazują na obiekty orignalne.Na obrazie utworzono nową kopię dla listy zewnętrznej. ale wewnętrzna lista pozostaje taka sama jak oryginalna.
Teraz tworzymy jego kopię za pomocą
z = copy.deepcopy(x)
. to, co robi tutaj Python, utworzy nowy obiekt zarówno dla listy zewnętrznej, jak i wewnętrznej. jak pokazano na poniższym obrazku (podświetlone na czerwono).Na końcu drukowany jest kod
False
, ponieważ y i z nie są tymi samymi obiektami.HTH.
źródło
Płytkie kopiowanie polega na utworzeniu nowego obiektu, a następnie skopiowaniu niestatycznych pól bieżącego obiektu na nowy obiekt. Jeśli pole jest typem wartości -> wykonywana jest kopia pola po kawałku; dla typu referencji -> referencja jest kopiowana, ale obiekt referencyjny nie jest; dlatego oryginalny obiekt i jego klon odnoszą się do tego samego obiektu.
Głębokie kopiowanie polega na utworzeniu nowego obiektu, a następnie skopiowaniu niestatycznych pól bieżącego obiektu na nowy obiekt. Jeśli pole jest typem wartości -> wykonywana jest kopia pola po kawałku. Jeśli pole jest typem odniesienia -> wykonywana jest nowa kopia obiektu, do którego następuje odwołanie . Klonowane klasy muszą zostać oznaczone jako [Serializable].
źródło
Zaczerpnięte z [blog]: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html
Głęboka kopia polega na użyciu zawartości jednego obiektu do utworzenia kolejnego wystąpienia tej samej klasy. W głębokiej kopii dwa obiekty mogą zawierać tę samą informację, ale obiekt docelowy będzie miał własne bufory i zasoby. zniszczenie jednego z obiektów nie wpłynie na pozostały obiekt. Przeciążony operator przypisania utworzyłby głęboką kopię obiektów.
Płytka kopia polega na skopiowaniu zawartości jednego obiektu do innej instancji tej samej klasy, tworząc w ten sposób odbicie lustrzane. Dzięki prostemu kopiowaniu odniesień i wskaźników oba obiekty będą dzielić tę samą zewnętrznie zawartą zawartość drugiego obiektu, aby były nieprzewidywalne.
Wyjaśnienie:
Za pomocą konstruktora kopiowania po prostu kopiujemy wartości danych członek po członku. Ta metoda kopiowania nazywa się płytką kopią. Jeśli obiekt jest prostą klasą, złożoną z wbudowanych typów i bez wskaźników, byłoby to do przyjęcia. Ta funkcja użyłaby wartości i obiektów, a jej zachowanie nie byłoby zmienione płytką kopią, kopiowane są tylko adresy wskaźników będących członkami, a nie wartość, na którą wskazuje adres. Wartości danych obiektu zostałyby wówczas przypadkowo zmienione przez funkcję. Gdy funkcja wykracza poza zakres, kopia obiektu wraz ze wszystkimi danymi jest usuwana ze stosu.
Jeśli obiekt ma jakieś wskaźniki, należy wykonać głęboką kopię. W przypadku głębokiej kopii obiektu pamięć jest przydzielana dla obiektu w magazynie wolnym, a wskazane elementy są kopiowane. Głęboka kopia jest używana dla obiektów zwracanych z funkcji.
źródło
Aby dodać więcej do innych odpowiedzi,
źródło
Płytka kopia nie utworzy nowego odwołania, ale głęboka kopia utworzy nowe odniesienie.
Oto program wyjaśniający głęboką i płytką kopię.
źródło
Kopiowanie ararysów:
Tablica jest klasą, co oznacza, że jest typem referencyjnym, więc tablica1 = tablica2 daje dwie zmienne, które odwołują się do tej samej tablicy.
Ale spójrz na ten przykład:
płytki klon oznacza, że kopiowana jest tylko pamięć reprezentowana przez sklonowaną tablicę.
Jeśli tablica zawiera obiekty typu wartości, wartości są kopiowane ;
jeśli tablica zawiera typ referencji, kopiowane są tylko referencje - w rezultacie istnieją dwie tablice, których członkowie odwołują się do tych samych obiektów .
Aby utworzyć głęboką kopię - w której powielone są typy referencji, należy zapętlić tablicę i ręcznie sklonować każdy element.
źródło
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]); }
Zrozumiałem z następujących wierszy.
Płytka kopia kopiuje pola typu wartości obiektu (int, float, bool) do obiektu docelowego, a typy referencyjne obiektu (ciąg znaków, klasa itp.) Są kopiowane jako odwołania do obiektu docelowego. W tym docelowym typie odniesienia będą wskazywać lokalizację pamięci obiektu źródłowego.
Głęboka kopia kopiuje wartość obiektu i typy referencji do kompletnej nowej kopii obiektów docelowych. Oznacza to, że zarówno typy wartości, jak i typy referencyjne zostaną przydzielone nowe lokalizacje pamięci.
źródło
Dodając do wszystkich powyższych definicji, jeszcze jedną i najczęściej używaną głęboką kopię, znajduje się w konstruktorze kopii (lub przeciążającym operatorze przypisania) klasy.
Płytka kopia -> ma miejsce, gdy nie udostępniasz konstruktora kopii. Tutaj kopiowany jest tylko obiekt, ale nie wszyscy członkowie klasy są kopiowani.
Głębokie kopiowanie -> ma miejsce, gdy zdecydujesz się na implementację konstruktora kopiowania lub przypisanie przeciążenia w swojej klasie i pozwala na skopiowanie wszystkich członków klasy.
źródło
Konstruktor kopiowania służy do inicjalizacji nowego obiektu za pomocą wcześniej utworzonego obiektu tej samej klasy. Domyślnie kompilator napisał płytką kopię. Płytka kopia działa dobrze, gdy dynamiczna alokacja pamięci nie jest zaangażowana, ponieważ gdy dynamiczna alokacja pamięci jest zaangażowana, oba obiekty będą wskazywały tę samą lokalizację pamięci na stercie, dlatego aby usunąć ten problem, napisaliśmy głęboką kopię, aby oba obiekty miały własną kopię atrybutów w pamięci. Aby przeczytać szczegóły z pełnymi przykładami i objaśnieniami, możesz przeczytać konstruktory w artykule C ++ .
źródło