Jaka jest różnica między kopią głęboką a płytką?


Odpowiedzi:


759

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.


Może być implementacją .NET MemberwiseClone () nie tylko płytkim kopiowaniem w konwencjonalnym znaczeniu
Lu55

5
Pamiętaj, że istnieją również kopie mieszane (nie tylko takie, jak leniwa kopia ), które kopiują tylko jej część ( tutaj jest instancja )! ;)
cregox 10.01.2015

Więc płytka kopia X może zmieniać elementy w X, ale głęboka kopia nie?
punstress

1
czym jest struktura kolekcji?
Kochanie,

1
@Honey Collections mogą być różnorodnymi strukturami danych, które przechowują wiele elementów danych. W pythonie mamy krotkę, listę, słowniki itp.
Murphy,

850

Szerokość vs głębokość; myśl w kategoriach drzewa odniesień z twoim obiektem jako węzłem głównym.

Płycizna:

Przed kopiowaniem Płytkie kopiowanie Shallow Done

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:

Przed kopiowaniem Głębokie kopiowanie Deep Done

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.


32
Oto artykuł w Wikipedii, z którego pochodzi ta ilustracja, na wypadek gdyby nie miała dla ciebie sensu z kontekstu en.wikipedia.org/wiki/Object_copy#Shallow_copy
corbin

4
W przypadku płytkiej kopii, jeśli dokonamy jakichkolwiek zmian w tablicy B, czy zostaną one odzwierciedlone w tablicy A, ponieważ zarówno A, jak i B wskazują na to samo miejsce w pamięci?
tek3

3
W jednej linii jego kopia przez odniesienie vs kopia według wartości. Nie jestem pewien, czy odpowiedź jest poprawna!
Mannu,

2
zdjęcia bezpośrednio z Wikipedii bez cytowania
jasonleonhard

9
@ jasonleonhard Więc 9 lat temu po prostu umieściłem adresy URL obrazów, ponieważ osadzanie obrazów nie było obsługiwane. W ten sposób adres URL podał swoje źródło. Społeczność później przekształciła adresy URL w osadzone obrazy bez edytowania cytatów. Top 4-letni komentarz również wskazuje na to, na co zwracasz uwagę. Zobacz: stackoverflow.com/posts/184780/revisions Dlaczego po prostu nie edytujesz cytatu w odpowiedzi? Mogę być niedostępny, gdy następnym razem ktoś narzeka na mój 10-letni styl pisania.
dlamblin,

156

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


112

Spróbuj rozważyć następujący obraz

wprowadź opis zdjęcia tutaj

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


28
Obraz jest wart tysiąca słów.
Levi Fuller

6
Och, chłopcze, przyjechałem tutaj, aby poznać znaczenie. To jedyna odpowiedź, która pomogła.
Karan Singh

1
Jest to najprostszy, a jednak pokazuje tylko to, co jest konieczne.
hina10531

1
najlepsza ilustracja
Muhammad Nayab

69

Specjalnie dla programistów iOS:

Jeśli Bjest to płytkie kopia z A, a następnie do pierwotnych danych to jak B = [A assign];i dla obiektów to jak B = [A retain];

B i A wskazują na to samo miejsce w pamięci

Jeśli Bjest głęboka kopia z A, 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


8
„Adres pamięci B jest taki sam jak adres A” - dlaczego?

2
W Deep Copy „adres pamięci B NIE jest taki sam jak adres A”
ismail baig

60

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:

class String
{
     int   size;
     char* data;
};

String  s1("Ace");   // s1.size = 3 s1.data=0x0000F000

String  s2 = shallowCopy(s1);
 // s2.size =3 s2.data = 0X0000F000
String  s3 = deepCopy(s1);
 // s3.size =3 s3.data = 0x0000F00F
 //                      (With Ace copied to this location.)

47

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.



36

{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.


32
char * Source = "Hello, world.";

char * ShallowCopy = Source;    

char * DeepCopy = new char(strlen(Source)+1);
strcpy(DeepCopy,Source);        

„ShallowCopy” wskazuje to samo miejsce w pamięci, co „Source”. „DeepCopy” wskazuje na inną lokalizację w pamięci, ale zawartość jest taka sama.


22

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.Płytka kopia

Na tym rysunku MainObject1ma pola field1typu int i ContainObject1typu ContainObject. Kiedy zrobisz płytką kopię MainObject1, MainObject2tworzony jest z field2zawartością skopiowanej wartości field1i nadal wskazuje na ContainObject1siebie. Zauważ, że skoro field1jest typu pierwotnego, jego wartość jest kopiowana, field2ale ponieważ ContainedObject1jest obiektem, MainObject2nadal wskazuje ContainObject1. Tak więc wszelkie zmiany wprowadzone ContainObject1w MainObject1zostaną odzwierciedlone w MainObject2.

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. Deep Copy

Na tym rysunku obiekt MainObject1 ma pola field1typu int i ContainObject1typu ContainObject. Po wykonaniu głębokiej kopii MainObject1, MainObject2jest tworzony z field2zawartością skopiowanej wartości field1i ContainObject2z wartością skopiowanej wartości ContainObject1. Uwaga: wszelkie zmiany wprowadzone w ContainObject1w MainObject1nie będą odzwierciedlone w MainObject2.

dobry artykuł


to nie twoja wina, chociaż ten przykład odnosi się do sytuacji, w field3któ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 miejsce ContainObject2 ?
Robb_2015

16

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.


12

„ShallowCopy” wskazuje to samo miejsce w pamięci, co „Source”. „DeepCopy” wskazuje na inną lokalizację w pamięci, ale zawartość jest taka sama.


Jest to nieco mylące. Zarówno płytka, jak i głęboka kopia skopiuje obiekt do nowej lokalizacji w pamięci, głęboka również skopiuje obiekty potomne, podczas gdy płytka będzie tylko, że nowe obiekty będą odnosić się do starych dzieci. Trudno go odczytać bez odniesienia do oryginalnego obiektu.
Bill K

10

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.

Employee e = new Employee(2, "john cena");
Employee e2=e.clone();

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:

Employee e = new Employee(2, "john cena", new Address(12, "West Newbury", "Massachusetts");

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.


8
var source = { firstName="Jane", lastname="Jones" };
var shallow = ShallowCopyOf(source);
var deep = DeepCopyOf(source);
source.lastName = "Smith";
WriteLine(source.lastName); // prints Smith
WriteLine(shallow.lastName); // prints Smith
WriteLine(deep.lastName); // prints Jones

To nie jest dobry przykład. Płytkie kopie są najczęściej używane do szybkiego kopiowania obiektów, bez kopiowania danych, ale gdy obiekt musi zmodyfikować udostępnione dane, pobierana jest głęboka kopia. Twój przykład prawdopodobnie pomyli początkujących.
CMircea

działa to tylko w językach, które używają wskaźników do reprezentowania ciągów. Chodzi o to, że DHA stara się, aby płytka kopia tylko kopiowała wskaźniki do identycznej (pojedynczej) oryginalnej zawartości, podczas gdy głęboka kopia klonuje również odnośnikową zawartość wskaźników. Obie metody kopiują zawartość powierzchni. Jeśli język przechowuje ciągi znaków jako dosłowną treść, np. W nagłówku WAV, ten przykład nie będzie działał. Zauważ, że jest to prawdopodobnie zbyt wybredne w przypadku większości rzeczywistych problemów, które nie są ezoteryczne.
DragonLord,

8

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.


Ten link niestety już nie działa - teraz wskazuje na artykuł z lutego 2019 r. Dotyczący projektowania stron internetowych (chyba że autor jest jasnowidzem?).
PhilPhil,

7

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.

klon zawsze wykonuje płytką kopię.

public class Language implements Cloneable{

    String name;
    public Language(String name){
        this.name=name;
    }

    public String getName() {
        return name;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

główna klasa jest następująca-

public static void main(String args[]) throws ClassNotFoundException, CloneNotSupportedException{

      ArrayList<Language> list=new ArrayList<Language>();
      list.add(new Language("C"));
      list.add(new Language("JAVA"));

      ArrayList<Language> shallow=(ArrayList<Language>) list.clone();
      //We used here clone since this always shallow copied.

      System.out.println(list==shallow);

      for(int i=0;i<list.size();i++)
      System.out.println(list.get(i)==shallow.get(i));//true

      ArrayList<Language> deep=new ArrayList<Language>();
      for(Language language:list){
          deep.add((Language) language.clone());
      }
      System.out.println(list==deep);
      for(int i=0;i<list.size();i++)
          System.out.println(list.get(i)==deep.get(i));//false

} 

OutPut powyżej będzie-

fałsz prawda prawda

fałszywy fałszywy fałszywy

Wszelkie zmiany dokonane w obiekcie pierwotnym będą odzwierciedlone w obiekcie płytkim, a nie w obiekcie głębokim.

  list.get(0).name="ViSuaLBaSiC";
  System.out.println(shallow.get(0).getName()+"  "+deep.get(0).getName());

OutPut- ViSuaLBaSiC C


7

Chciałbym podać przykład zamiast formalnej definicji.

var originalObject = { 
    a : 1, 
    b : 2, 
    c : 3,
};

Ten kod pokazuje płytką kopię :

var copyObject1 = originalObject;

console.log(copyObject1.a);         // it will print 1 
console.log(originalObject.a);       // it will also print 1 
copyObject1.a = 4; 
console.log(copyObject1.a);           //now it will print 4 
console.log(originalObject.a);       // now it will also print 4

var copyObject2 = Object.assign({}, originalObject);

console.log(copyObject2.a);        // it will print 1 
console.log(originalObject.a);      // it will also print 1 
copyObject2.a = 4; 
console.log(copyObject2.a);        // now it will print 4 
console.log(originalObject.a);      // now it will print 1

Ten kod pokazuje głęboką kopię :

var copyObject2 = Object.assign({}, originalObject);

console.log(copyObject2.a);        // it will print 1 
console.log(originalObject.a);      // it will also print 1 
copyObject2.a = 4; 
console.log(copyObject2.a);        // now it will print 4 
console.log(originalObject.a);      // !! now it will print 1 !!

Dostaję1 1 4 4 4 4 4 4
Suresh Prajapati

w głębokiej kopii wykonaj copyObject.a = 8, a następnie sprawdź. mam nadzieję, że dostaniesz właściwą odpowiedź.
Vivek Mehta,

5
struct sample
{
    char * ptr;
}
void shallowcpy(sample & dest, sample & src)
{
    dest.ptr=src.ptr;
}
void deepcpy(sample & dest, sample & src)
{
    dest.ptr=malloc(strlen(src.ptr)+1);
    memcpy(dest.ptr,src.ptr);
}

5

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ść.


5

Wyobraź sobie, że istnieją dwie tablice zwane arr1 i arr2.

arr1 = arr2;   //shallow copy
arr1 = arr2.clone(); //deep copy

5

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.

import copy
x =[1,[2]]
y=copy.copy(x)
z= copy.deepcopy(x)
print(y is z)

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))

wprowadź opis zdjęcia tutaj

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.

wprowadź opis zdjęcia tutaj

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).

wprowadź opis zdjęcia tutaj

Na końcu drukowany jest kod False, ponieważ y i z nie są tymi samymi obiektami.

HTH.


2

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].


2

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.


2

Aby dodać więcej do innych odpowiedzi,

  • Płytka kopia obiektu wykonuje kopiowanie według wartości dla właściwości opartych na typach wartości i kopiowanie przez odniesienie dla właściwości opartych na typach referencyjnych.
  • Głęboka kopia obiektu wykonuje kopiowanie według wartości dla właściwości opartych na typach wartości, a także kopiowanie według wartości dla właściwości opartych na typach referencyjnych głęboko w hierarchii (typów referencyjnych)

2

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ę.

public class DeepAndShollowCopy {
    int id;
    String name;
    List<String> testlist = new ArrayList<>();

    /*
    // To performing Shallow Copy 
    // Note: Here we are not creating any references. 
      public DeepAndShollowCopy(int id, String name, List<String>testlist)
       { 

       System.out.println("Shallow Copy for Object initialization");
       this.id = id; 
       this.name = name; 
       this.testlist = testlist; 

       }
    */  

    // To performing Deep Copy 
    // Note: Here we are creating one references( Al arraylist object ). 
    public DeepAndShollowCopy(int id, String name, List<String> testlist) {
        System.out.println("Deep Copy for Object initialization");
        this.id = id;
        this.name = name;
        String item;
        List<String> Al = new ArrayList<>();
        Iterator<String> itr = testlist.iterator();
        while (itr.hasNext()) {
            item = itr.next();
            Al.add(item);
        }
        this.testlist = Al;
    }


    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Oracle");
        list.add("C++");
        DeepAndShollowCopy copy=new DeepAndShollowCopy(10,"Testing", list);
        System.out.println(copy.toString());
    }
    @Override
    public String toString() {
        return "DeepAndShollowCopy [id=" + id + ", name=" + name + ", testlist=" + testlist + "]";
    }
}

1

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:

  static void Main()
    {
        int[] arr1 = new int[] { 1, 2, 3, 4, 5 }; 
        int[] arr2 = new int[] { 6, 7, 8, 9, 0 };

        Console.WriteLine(arr1[2] + " " + arr2[2]);
        arr2 = arr1;
        Console.WriteLine(arr1[2] + " " + arr2[2]); 
        arr2 = (int[])arr1.Clone();
        arr1[2] = 12;
        Console.WriteLine(arr1[2] + " " + arr2[2]);
    }

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.


Nie znam innych języków, ale w C # / VB płytkie kopiowanie tablicy typów wartości nie kopiuje wartości. Dwie tablice odnoszą się do tych samych obiektów. Dodaj przycisk do formularza i dodaj ten kod, aby zobaczyć: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]); }
DeanOC,

masz rację, poprawiłem moją odpowiedź, aby była bardziej precyzyjna, używając klonowania na tablicach. Masz całkowitą rację, że „płytkie kopiowanie tablicy typów wartości nie kopiuje wartości”, ale robi to za pomocą klonowania na tablicy. Próbowałem to wyjaśnić, spróbuj. Dzięki
lukaszk,

1

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.


0

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.

MyClass& MyClass(const MyClass& obj) // copy constructor for MyClass
{
          // write your code, to copy all the members and return the new object
}
MyClass& operator=(const MyClass& obj) // overloading assignment operator,
{
          // write your code, to copy all the members and return the new object
}

0

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 ++ .

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.