Qual è la differenza tra una copia profonda e una copia superficiale?


754

Qual è la differenza tra una copia profonda e una copia superficiale?


6
Quale tecnologia viene sotto?
Suresh Varma,

42
@SureshVarma, è un concetto di programmazione!
Manish Shrivastava,

Risposte:


762

Copie poco profonde duplicate il meno possibile. Una copia superficiale di una raccolta è una copia della struttura della raccolta, non degli elementi. Con una copia superficiale, due raccolte ora condividono i singoli elementi.

Le copie profonde duplicano tutto. Una copia profonda di una raccolta sono due raccolte con tutti gli elementi della raccolta originale duplicati.


Potrebbe essere l'implementazione di .NET MemberwiseClone () fare più di una copia superficiale in senso convenzionale
Lu55,

5
Tieni presente che ci sono anche copie miste (non solo come copia pigra ), che ne duplica solo una parte ( ecco un'istanza )! ;)
cregox,

Quindi una copia superficiale di X può cambiare gli elementi in X ma una copia profonda non può?
punstress

1
che cos'è una struttura di raccolta?
Miele,

1
Le raccolte @Honey possono essere diverse strutture di dati che memorizzano più elementi di dati. In pitone abbiamo tupla, lista, dizione, ecc.
Murphy

852

Larghezza vs Profondità; pensa in termini di un albero di riferimenti con il tuo oggetto come nodo radice.

Shallow:

Prima della copia Copia superficiale Superficiale

Le variabili A e B si riferiscono a diverse aree di memoria, quando B è assegnato ad A le due variabili si riferiscono alla stessa area di memoria. Modifiche successive al contenuto di uno dei due si riflettono istantaneamente nel contenuto dell'altro, poiché condividono il contenuto.

In profondità:

Prima della copia Copia profonda Fatto

Le variabili A e B si riferiscono a diverse aree della memoria, quando B è assegnato ad A i valori nell'area di memoria in cui A punta sono copiati nell'area di memoria in cui B indica. Modifiche successive al contenuto di entrambi rimangono uniche per A o B; i contenuti non sono condivisi.


33
Ecco l'articolo di Wikipedia da cui proviene questa illustrazione nel caso in cui non abbia senso fuori contesto per te en.wikipedia.org/wiki/Object_copy#Shallow_copy
corbin

4
In caso di copia superficiale se si apportano modifiche all'array B, ciò si rifletterà nell'array A poiché A e B indicano entrambi la stessa posizione di memoria?
tek3,

3
In linea singola la sua copia per riferimento vs copia per valore. Non sono sicuro che la risposta sia corretta!
Mannu,

2
immagini tratte direttamente da Wikipedia senza citazione
jasonleonhard,

10
@jasonleonhard Così, 9 anni fa, ho appena inserito gli URL per le immagini perché l'incorporamento delle immagini non era supportato. Quindi l'URL ha citato la sua fonte. Successivamente la community ha trasformato gli URL in immagini incorporate senza modificare alcun tipo di citazione. Il primo commento di 4 anni sottolinea anche ciò che fai notare. Dai un'occhiata: stackoverflow.com/posts/184780/revisions Perché non modificare tu stesso una citazione nella risposta? Potrei non essere disponibile la prossima volta che qualcuno avrà qualche lamentela sul mio stile di scrittura di 10 anni.
dlamblin,

156

In breve, dipende da cosa indica cosa. In una copia superficiale, l'oggetto B indica la posizione dell'oggetto A in memoria. Nella copia profonda, tutte le cose nella posizione di memoria dell'oggetto A vengono copiate nella posizione di memoria dell'oggetto B.

Questo articolo wiki ha un diagramma fantastico.

http://en.wikipedia.org/wiki/Object_copy


114

Prova a considerare la seguente immagine

inserisci qui la descrizione dell'immagine

Ad esempio Object.MemberwiseClone crea un collegamento di copia superficiale

e usando l' interfaccia ICloneable puoi ottenere una copia approfondita come descritto qui


28
Un'immagine vale più di mille parole.
Levi Fuller,

6
Oh ragazzo, sono venuto qui per scoprire il significato. Questa è l'unica risposta che ha aiutato.
Karan Singh,

1
Questo è il più semplice e mostra solo ciò che è necessario.
hina10531

1
la migliore illustrazione
Muhammad Nayab il

69

Soprattutto per gli sviluppatori iOS:

Se Bè una copia superficiale di A, allora per i dati primitivi è simile B = [A assign];e per gli oggetti è simile B = [A retain];

B e A indicano la stessa posizione di memoria

Se Bè una copia profonda di A, allora è comeB = [A copy];

B e A indicano diverse posizioni di memoria

L'indirizzo di memoria B è uguale a quello di A.

B ha gli stessi contenuti di A


8
"L'indirizzo di memoria B è uguale a quello di A" - Come mai?

2
In Deep Copy, "L'indirizzo di memoria B NON è uguale a quello di A"
ismail baig

60

Copia superficiale: copia i valori dei membri da un oggetto a un altro.

Deep Copy: copia i valori dei membri da un oggetto a un altro.
                     Tutti gli oggetti puntatore vengono duplicati e copiati in profondità.

Esempio:

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

Non ho visto una risposta breve e facile da capire qui - quindi ci proverò.

Con una copia superficiale, qualsiasi oggetto a cui punta l'origine viene anche indicato dalla destinazione (in modo che nessun oggetto referenziato venga copiato).

Con una copia profonda, qualsiasi oggetto a cui punta l'origine viene copiato e la copia viene puntata dalla destinazione (quindi ora ci saranno 2 di ogni oggetto a cui viene fatto riferimento). Ciò ricorre verso il basso l'albero degli oggetti.



36

{Immagina due oggetti: A e B dello stesso tipo _t (rispetto a C ++) e stai pensando di copiare superficialmente / in profondità da A a B}

Copia superficiale: crea semplicemente una copia del riferimento ad A in B. Pensa a questo come una copia dell'indirizzo di A. Pertanto, gli indirizzi di A e B saranno gli stessi, ovvero indicheranno la stessa posizione di memoria, ovvero il contenuto dei dati.

Copia profonda: crea semplicemente una copia di tutti i membri di A, alloca la memoria in una posizione diversa per B e quindi assegna i membri copiati a B per ottenere la copia profonda. In questo modo, se A diventa inesistente, B è ancora valido nella memoria. Il termine corretto da utilizzare sarebbe la clonazione, in cui si sa che entrambi sono totalmente uguali, ma tuttavia diversi (ovvero memorizzati come due entità diverse nello spazio di memoria). È inoltre possibile fornire il proprio wrapper clone in cui è possibile decidere tramite l'elenco di inclusione / esclusione quali proprietà selezionare durante la copia approfondita. Questa è una pratica abbastanza comune quando si creano API.

Puoi scegliere di fare una copia superficiale SOLO_IF hai capito la posta in gioco. Quando hai un numero enorme di puntatori da gestire in C ++ o C, fare una copia superficiale di un oggetto è DAVVERO una cattiva idea.

EXAMPLE_OF_DEEP COPY_ Un esempio è, quando si sta tentando di eseguire l'elaborazione delle immagini e il riconoscimento degli oggetti, è necessario mascherare "Movimento irrilevante e ripetitivo" dalle aree di elaborazione. Se si utilizzano i puntatori di immagini, è possibile che si disponga delle specifiche per salvare quelle immagini di maschere. ORA ... se si esegue una copia superficiale dell'immagine, quando i riferimenti del puntatore vengono KILLED dallo stack, si perde il riferimento e la sua copia, cioè ad un certo punto si verificherà un errore di runtime della violazione di accesso. In questo caso, ciò di cui hai bisogno è una copia profonda della tua immagine CLONANDO. In questo modo è possibile recuperare le maschere nel caso in cui siano necessarie in futuro.

EXAMPLE_OF_SHALLOW_COPY Non sono estremamente informato rispetto agli utenti di StackOverflow, quindi sentiti libero di eliminare questa parte e di dare un buon esempio se puoi chiarire. Ma penso davvero che non sia una buona idea fare una copia superficiale se sai che il tuo programma verrà eseguito per un periodo di tempo infinito, ad esempio un'operazione "push-pop" continua sullo stack con chiamate di funzione. Se stai dimostrando qualcosa a una persona dilettante o alle prime armi (ad esempio materiale didattico C / C ++), probabilmente va bene. Ma se stai eseguendo un'applicazione come il sistema di sorveglianza e rilevamento o Sonar Tracking System, non dovresti continuare a copiare superficialmente i tuoi oggetti perché prima o poi ucciderà il tuo programma.


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

char * ShallowCopy = Source;    

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

'ShallowCopy' indica la stessa posizione in memoria di 'Fonte'. 'DeepCopy' indica una diversa posizione nella memoria, ma i contenuti sono gli stessi.


22

Che cos'è la copia superficiale?

La copia superficiale è una copia bit-saggia di un oggetto. Viene creato un nuovo oggetto che ha una copia esatta dei valori nell'oggetto originale. Se uno qualsiasi dei campi dell'oggetto è riferimento ad altri oggetti, vengono copiati solo gli indirizzi di riferimento, ovvero viene copiato solo l'indirizzo di memoria.Copia superficiale

In questa figura, MainObject1ha campi field1di tipo int e ContainObject1di tipo ContainObject. Quando si esegue una copia superficiale di MainObject1, MainObject2viene creato field2contenente il valore copiato di field1e puntando ancora a ContainObject1se stesso. Si noti che poiché field1è di tipo primitivo, il suo valore viene copiato field2ma poiché ContainedObject1è un oggetto, MainObject2punta ancora a ContainObject1. Pertanto, qualsiasi modifica apportata a ContainObject1in MainObject1verrà riflessa in MainObject2.

Ora, se questa è copia superficiale, vediamo cos'è la copia profonda?

Che cos'è Deep Copy?

Una copia profonda copia tutti i campi e crea copie della memoria allocata dinamicamente indicata dai campi. Una copia profonda si verifica quando un oggetto viene copiato insieme agli oggetti a cui si riferisce. Deep Copy

In questa figura, MainObject1 ha campi field1di tipo int e ContainObject1di tipo ContainObject. Quando si esegue una copia profonda di MainObject1, MainObject2viene creato field2contenente il valore copiato di field1e ContainObject2contenente il valore copiato di ContainObject1. Si noti che eventuali modifiche apportate a ContainObject1in MainObject1non si riflettono in MainObject2.

buon articolo


non è colpa tua se questo esempio si riferisce a un field3che quando è in grado di provare a comprendere qualcosa di così profondo come quel problema, dove sta avvenendo quel numero 3 in quell'esempio ContainObject2 ?
Robb_2015,

16

Nella programmazione orientata agli oggetti, un tipo include una raccolta di campi membri. Questi campi possono essere memorizzati per valore o per riferimento (ad esempio, un puntatore a un valore).

In una copia superficiale, viene creata una nuova istanza del tipo e i valori vengono copiati nella nuova istanza. Anche i puntatori di riferimento vengono copiati proprio come i valori. Pertanto, i riferimenti puntano agli oggetti originali. Eventuali modifiche ai membri archiviate per riferimento vengono visualizzate sia nell'originale che nella copia, poiché non è stata effettuata alcuna copia dell'oggetto a cui si fa riferimento.

In una copia profonda, i campi memorizzati per valore vengono copiati come prima, ma i puntatori agli oggetti memorizzati per riferimento non vengono copiati. Al contrario, viene eseguita una copia approfondita dell'oggetto a cui viene fatto riferimento e viene memorizzato un puntatore al nuovo oggetto. Eventuali modifiche apportate a tali oggetti referenziati non influiranno su altre copie dell'oggetto.


12

'ShallowCopy' indica la stessa posizione in memoria di 'Fonte'. 'DeepCopy' indica una diversa posizione nella memoria, ma i contenuti sono gli stessi.


Questo è leggermente fuorviante. Sia una copia superficiale che una copia profonda copieranno l'oggetto in una nuova posizione in memoria, una copia profonda copierà anche gli oggetti figlio mentre una copia superficiale avrà solo i nuovi oggetti che si riferiscono ai bambini più vecchi. È difficile da leggere senza fare riferimento all'oggetto originale.
Bill K,

10

Clonazione superficiale:
definizione: "Una copia superficiale di un oggetto copia l'oggetto" principale ", ma non copia gli oggetti interni." Quando un oggetto personalizzato (es. Employee) ha solo variabili primitive di tipo String, allora si usa la clonazione superficiale.

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

Si ritorna super.clone();nel metodo clone () ignorato e il lavoro è finito.

Deep Cloning :
Definizione: "A differenza della copia superficiale, una copia profonda è una copia completamente indipendente di un oggetto."
Significa quando un oggetto Employee contiene un altro oggetto personalizzato:

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

Quindi devi scrivere il codice per clonare anche l'oggetto "Indirizzo" nel metodo clone () ignorato. Altrimenti l'oggetto Indirizzo non clonerà e causerà un bug quando cambi il valore di Indirizzo nell'oggetto Dipendente clonato, che riflette anche quello originale.


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

Questo non è un buon esempio. Le copie superficiali vengono utilizzate principalmente per la copia rapida di oggetti, senza copiare i dati, ma una volta che un oggetto deve modificare i dati condivisi, viene eseguita una copia profonda di questi. Il tuo esempio probabilmente confonderà i principianti.
CMircea,

funziona solo nelle lingue che usano i puntatori per rappresentare le stringhe. Il punto che DHA sta cercando di fare è che la copia superficiale duplica solo i puntatori allo stesso identico contenuto (singolare), mentre la copia profonda clona anche il contenuto di riferimento dei puntatori. Entrambi i metodi copiano il contenuto della superficie. Se la lingua memorizza le stringhe come contenuto letterale di superficie, ad esempio all'interno di un'intestazione WAV, questo esempio non funzionerà. Nota che questo è probabilmente troppo esigente per la maggior parte dei problemi della vita reale che non sono esoterici.
DragonLord

8

Deep Copy

Una copia profonda copia tutti i campi e crea copie della memoria allocata dinamicamente indicata dai campi. Una copia profonda si verifica quando un oggetto viene copiato insieme agli oggetti a cui si riferisce.

Copia superficiale

La copia superficiale è una copia bit-saggia di un oggetto. Viene creato un nuovo oggetto che ha una copia esatta dei valori nell'oggetto originale. Se uno qualsiasi dei campi dell'oggetto è riferimento ad altri oggetti, vengono copiati solo gli indirizzi di riferimento, cioè viene copiato solo l'indirizzo di memoria.


Questo link purtroppo non funziona più - ora indica un articolo di febbraio 2019 relativo al web design (a meno che l'autore non sia chiaroveggente?).
PhilPhil

7

Copia superficiale : la variabile di riferimento all'interno di oggetti originali e di copia superficiale fa riferimento all'oggetto comune .

Deep Copy - Le variabili di riferimento all'interno di oggetti originali e copiati in profondità hanno riferimenti a oggetti diversi .

clone esegue sempre una copia superficiale.

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();
    }
}

la classe principale sta seguendo-

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 di cui sopra sarà-

falso vero vero

falso falso falso

Qualsiasi modifica apportata all'oggetto originale si rifletterà nell'oggetto superficiale non nell'oggetto profondo.

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

OutPut- ViSuaLBaSiC C


7

Vorrei fare un esempio piuttosto che una definizione formale.

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

Questo codice mostra una copia superficiale :

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

Questo codice mostra una copia profonda :

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

Ricevo1 1 4 4 4 4 4 4
Suresh Prajapati l'

in deep copy, copia copyObject.a = 8 e quindi controlla. spero che otterrai una risposta adeguata.
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

In termini semplici, una copia superficiale è simile a Chiama per riferimento e una copia profonda è simile a Chiama per valore

In Call By Reference, sia i parametri formali che quelli effettivi di una funzione si riferiscono alla stessa posizione di memoria e al valore.

In Call By Value, sia i parametri formali che quelli effettivi di una funzione si riferiscono a posizioni di memoria diverse ma con lo stesso valore.


5

Immagina che ci siano due array chiamati arr1 e arr2.

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

5

Una copia superficiale costruisce un nuovo oggetto composto e inserisce i relativi riferimenti nell'oggetto originale.

A differenza della copia superficiale, la deepcopy costruisce un nuovo oggetto composto e inserisce anche copie degli oggetti originali dell'oggetto composto originale.

Facciamo un esempio.

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

Il codice sopra stampa FALSO.

Vediamo come.

Oggetto composto originale x=[1,[2]](chiamato come composto perché ha oggetto all'interno dell'oggetto (Inception))

inserisci qui la descrizione dell'immagine

come puoi vedere nell'immagine, c'è un elenco all'interno dell'elenco.

Quindi ne creiamo una copia superficiale usando y = copy.copy(x). Quello che Python fa qui è, creerà un nuovo oggetto composto ma gli oggetti al loro interno puntano verso gli oggetti originali.

inserisci qui la descrizione dell'immagine

Nell'immagine ha creato una nuova copia per l'elenco esterno. ma l'elenco interno rimane lo stesso di quello originale.

Ora ne creiamo una copia completa usando z = copy.deepcopy(x). ciò che python fa qui è, creerà un nuovo oggetto sia per la lista esterna che per quella interna. come mostrato nell'immagine seguente (rosso evidenziato).

inserisci qui la descrizione dell'immagine

Alla fine il codice viene stampato False, poiché y e z non sono gli stessi oggetti.

HTH.


2

La copia superficiale sta creando un nuovo oggetto e quindi copiando i campi non statici dell'oggetto corrente nel nuovo oggetto. Se un campo è un tipo di valore -> viene eseguita una copia bit per bit del campo; per un tipo di riferimento -> il riferimento viene copiato ma l'oggetto indicato non lo è; pertanto l'oggetto originale e il suo clone si riferiscono allo stesso oggetto.

Deep copia sta creando un nuovo oggetto e quindi copiando i campi non statici dell'oggetto corrente nel nuovo oggetto. Se un campo è un tipo di valore -> viene eseguita una copia bit per bit del campo. Se un campo è un tipo di riferimento -> viene eseguita una nuova copia dell'oggetto riferito. Le classi da clonare devono essere contrassegnate come [Serializable].


2

Tratto da [blog]: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

La copia profonda implica l'utilizzo del contenuto di un oggetto per creare un'altra istanza della stessa classe. In una copia profonda, i due oggetti possono contenere le stesse informazioni ma l'oggetto di destinazione avrà i propri buffer e risorse. la distruzione di entrambi gli oggetti non influirà sull'oggetto rimanente. L'operatore di assegnazione sovraccarico creerebbe una copia profonda degli oggetti.

La copia superficiale implica la copia del contenuto di un oggetto in un'altra istanza della stessa classe creando così un'immagine speculare. A causa della copia diretta di riferimenti e puntatori, i due oggetti condivideranno gli stessi contenuti contenuti esternamente dell'altro oggetto in modo imprevedibile.

Spiegazione:

Usando un costruttore di copie semplicemente copiamo i valori dei dati membro per membro. Questo metodo di copia si chiama copia superficiale. Se l'oggetto è una classe semplice, composta da tipi predefiniti e senza puntatori, ciò sarebbe accettabile. Questa funzione userebbe i valori e gli oggetti e il suo comportamento non verrebbe modificato con una copia superficiale, solo gli indirizzi dei puntatori che sono membri vengono copiati e non il valore a cui punta l'indirizzo. I valori dei dati dell'oggetto verrebbero quindi inavvertitamente modificati dalla funzione. Quando la funzione non rientra nell'ambito, la copia dell'oggetto con tutti i suoi dati viene espulsa dallo stack.

Se l'oggetto ha dei puntatori, è necessario eseguire una copia profonda. Con la copia profonda di un oggetto, la memoria viene allocata per l'oggetto nell'archivio libero e gli elementi puntati vengono copiati. Una copia profonda viene utilizzata per gli oggetti restituiti da una funzione.


2

Per aggiungere altro ad altre risposte,

  • una copia superficiale di un oggetto esegue la copia in base al valore per le proprietà basate sui tipi di valore e la copia per riferimento per le proprietà basate sui tipi di riferimento.
  • una Deep Copy di un oggetto esegue la copia in base al valore per le proprietà basate sui tipi di valore, nonché la copia in base al valore per le proprietà basate sui tipi di riferimento in profondità nella gerarchia (dei tipi di riferimento)

2

La copia superficiale non creerà un nuovo riferimento, ma la copia profonda creerà il nuovo riferimento.

Ecco il programma per spiegare la copia profonda e superficiale.

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

Copia di array:

L'array è una classe, il che significa che è un tipo di riferimento, quindi array1 = array2 risulta in due variabili che fanno riferimento allo stesso array.

Ma guarda questo esempio:

  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]);
    }

clone superficiale significa che viene copiata solo la memoria rappresentata dall'array clonato.

Se l'array contiene oggetti di tipo valore, i valori vengono copiati ;

se l'array contiene un tipo di riferimento, vengono copiati solo i riferimenti, quindi di conseguenza ci sono due array i cui membri fanno riferimento agli stessi oggetti .

Per creare una copia profonda, in cui i tipi di riferimento sono duplicati, è necessario eseguire il ciclo continuo dell'array e clonare manualmente ciascun elemento.


Non conosco altre lingue, ma in C # / VB, la copia superficiale di una matrice di tipi di valore non copia i valori. Le due matrici si riferiscono agli stessi oggetti. Aggiungi un pulsante a un modulo e aggiungi questo codice per visualizzare: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]); }
DecanoOC

hai ragione, ho corretto la mia risposta per essere più preciso, usando il clone sugli array. Hai assolutamente ragione che "la copia superficiale di una matrice di tipi di valore non copia i valori", ma l'utilizzo di clone su matrice lo fa. Ho provato a spiegarlo, provalo. Grazie
lukaszk il

1

Sono arrivato a capire dalle seguenti righe.

Copia superficiale copia i campi di un tipo di valore oggetto (int, float, bool) nell'oggetto target e i tipi di riferimento dell'oggetto (stringa, classe ecc.) Vengono copiati come riferimenti nell'oggetto target. In questo target, i tipi di riferimento indicheranno la posizione di memoria dell'oggetto sorgente.

Deep copy copia il valore di un oggetto e i tipi di riferimento in una nuova copia completa degli oggetti target. Ciò significa che sia ai tipi di valore che ai tipi di riferimento verrà assegnata una nuova posizione di memoria.


0

L'aggiunta a tutte le definizioni di cui sopra, un'altra copia profonda più comunemente usata, si trova nel costruttore della copia (o sovraccarico dell'assegnatore di funzioni) della classe.

Copia superficiale -> è quando non si fornisce il costruttore di copie. Qui viene copiato solo l'oggetto ma non tutti i membri della classe vengono copiati.

Deep copy -> è quando hai deciso di implementare il costruttore di copie o l'assegnazione del sovraccarico nella tua classe e ti permette di copiare tutti i membri della classe.

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

Il costruttore della copia viene utilizzato per inizializzare il nuovo oggetto con l'oggetto precedentemente creato della stessa classe. Di default il compilatore ha scritto una copia superficiale. La copia superficiale funziona correttamente quando non è coinvolta l'allocazione dinamica della memoria perché quando è coinvolta l'allocazione dinamica della memoria, entrambi gli oggetti punteranno verso la stessa posizione di memoria in un heap, pertanto per rimuovere questo problema abbiamo scritto una copia profonda in modo che entrambi gli oggetti abbiano una propria copia degli attributi in un ricordo. Per leggere i dettagli con esempi e spiegazioni complete, è possibile vedere i costruttori dell'articolo C ++ .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.