Quelle est la différence entre une copie profonde et une copie peu profonde?


754

Quelle est la différence entre une copie profonde et une copie peu profonde?


6
De quelle technologie relève-t-il?
Suresh Varma

42
@SureshVarma, c'est un concept de programmation!
Manish Shrivastava

Réponses:


763

Les copies superficielles dupliquent le moins possible. Une copie superficielle d'une collection est une copie de la structure de la collection, pas des éléments. Avec une copie superficielle, deux collections partagent désormais les éléments individuels.

Les copies profondes reproduisent tout. Une copie complète d'une collection est constituée de deux collections avec tous les éléments de la collection d'origine dupliqués.


L'implémentation de .NET MemberwiseClone () peut faire plus que la copie superficielle au sens conventionnel
Lu55

5
Gardez à l'esprit qu'il existe également des copies mixtes (non seulement telles que la copie paresseuse ), qui en dupliquent seulement une partie ( voici un exemple )! ;)
cregox

Une copie superficielle de X peut donc modifier les éléments de X, mais pas une copie complète?
punstress

1
qu'est-ce qu'une structure de collection?
Honey

1
Les collections @Honey peuvent être des structures de données diverses qui stockent plusieurs éléments de données. En python, nous avons tuple, liste, dictionnaires, etc.
Murphy

852

Largeur vs profondeur; pensez en termes d'arbre de références avec votre objet comme nœud racine.

Peu profond:

Avant la copie Copie peu profonde Shallow Done

Les variables A et B se réfèrent à différentes zones de mémoire, lorsque B est affecté à A, les deux variables se réfèrent à la même zone de mémoire. Les modifications ultérieures du contenu de l'un ou de l'autre se reflètent instantanément dans le contenu de l'autre, car elles partagent le contenu.

Profond:

Avant la copie Copie profonde Deep Done

Les variables A et B font référence à différentes zones de mémoire, lorsque B est affecté à A, les valeurs de la zone de mémoire vers lesquelles A pointe sont copiées dans la zone de mémoire vers laquelle B pointe. Les modifications ultérieures du contenu de l'un ou l'autre restent propres à A ou B; le contenu n'est pas partagé.


33
Voici l'article de wikipedia dont cette illustration vient au cas où cela n'aurait pas de sens hors contexte pour vous en.wikipedia.org/wiki/Object_copy#Shallow_copy
corbin

4
En cas de copie superficielle si nous apportons des modifications dans le tableau B, cela se reflétera-t-il dans le tableau A puisque A et B pointent tous deux vers le même emplacement mémoire?
tek3

3
En une seule ligne sa copie par référence vs copie par valeur. Je ne sais pas si la réponse est correcte!
Mannu

2
images directement tirées de wikipedia sans citation
jasonleonhard

10
@jasonleonhard Il y a donc 9 ans, je viens de mettre des URL sur les images car l'intégration d'images n'était pas prise en charge. Ainsi, l'URL a cité sa source. La communauté a ensuite transformé les URL en images incorporées sans y éditer une sorte de citation. Le commentaire en haut de 4 ans souligne également ce que vous signalez. Jetez un œil: stackoverflow.com/posts/184780/revisions Pourquoi ne pas simplement éditer une citation dans la réponse vous-même? Je serai peut-être indisponible la prochaine fois que quelqu'un se plaindra de mon style d'écriture de 10 ans.
dlamblin

156

En bref, cela dépend de ce qui indique quoi. Dans une copie superficielle, l'objet B pointe vers l'emplacement de l'objet A en mémoire. En copie profonde, tout ce qui se trouve dans l'emplacement de mémoire de l'objet A est copié dans l'emplacement de mémoire de l'objet B.

Cet article wiki a un grand diagramme.

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


115

Essayez de considérer l'image suivante

entrez la description de l'image ici

Par exemple, Object.MemberwiseClone crée un lien de copie superficiel

et en utilisant l' interface ICloneable , vous pouvez obtenir une copie complète comme décrit ici


28
Une image vaut mieux que mille mots.
Levi Fuller

6
Oh mon garçon, je suis venu ici pour trouver le sens C'est la seule réponse qui a aidé.
Karan Singh

1
C'est le plus simple et ne montre que ce qui est nécessaire.
hina10531

1
la meilleure illustration
Muhammad Nayab

69

Surtout pour les développeurs iOS:

Si Best une copie superficielle de A, alors pour les données primitives c'est comme B = [A assign];et pour les objets c'est comme B = [A retain];

B et A pointent vers le même emplacement mémoire

Si Bc'est une copie complète de A, alors c'est commeB = [A copy];

B et A pointent vers des emplacements de mémoire différents

L'adresse mémoire B est la même que celle de A

B a le même contenu que les A


8
"L'adresse mémoire B est la même que celle de A" - Comment ça se fait?

2
Dans Deep Copy, "l'adresse mémoire B n'est PAS la même que celle de A"
ismail baig

60

Copie superficielle: copie les valeurs des membres d'un objet dans un autre.

Deep Copy: copie les valeurs des membres d'un objet dans un autre.
                     Tous les objets pointeurs sont dupliqués et copiés en profondeur.

Exemple:

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

Je n'ai pas vu de réponse courte et facile à comprendre ici - je vais donc essayer.

Avec une copie superficielle, tout objet pointé par la source est également pointé par la destination (afin qu'aucun objet référencé ne soit copié).

Avec une copie complète, tout objet pointé par la source est copié et la copie est pointée par la destination (il y aura donc maintenant 2 de chaque objet référencé). Cela revient dans l'arborescence des objets.



36

{Imaginez deux objets: A et B de même type _t (par rapport à C ++) et vous songez à copier de façon superficielle / profonde A vers B}

Copie peu profonde: fait simplement une copie de la référence à A dans B. Considérez-la comme une copie de l'adresse de A. Ainsi, les adresses de A et B seront les mêmes, c'est-à-dire qu'elles pointeront vers le même emplacement de mémoire, c'est-à-dire le contenu des données.

Copie profonde: fait simplement une copie de tous les membres de A, alloue de la mémoire dans un emplacement différent pour B, puis attribue les membres copiés à B pour obtenir une copie profonde. De cette façon, si A devient inexistant, B est toujours valide dans la mémoire. Le terme correct à utiliser serait le clonage, où vous savez qu'ils sont tous deux identiques, mais pourtant différents (c'est-à-dire stockés comme deux entités différentes dans l'espace mémoire). Vous pouvez également fournir votre wrapper de clone où vous pouvez décider via la liste d'inclusion / exclusion quelles propriétés sélectionner pendant la copie complète. C'est une pratique assez courante lorsque vous créez des API.

Vous pouvez choisir de faire une copie superficielle UNIQUEMENT si vous comprenez les enjeux impliqués. Lorsque vous avez un nombre énorme de pointeurs à gérer en C ++ ou C, faire une copie superficielle d'un objet est VRAIMENT une mauvaise idée.

EXAMPLE_OF_DEEP COPY_ Par exemple, lorsque vous essayez de faire un traitement d'image et une reconnaissance d'objet, vous devez masquer les "mouvements non pertinents et répétitifs" hors de vos zones de traitement. Si vous utilisez des pointeurs d'image, vous pourriez avoir la spécification pour enregistrer ces images de masque. MAINTENANT ... si vous faites une copie superficielle de l'image, lorsque les références de pointeur sont TUÉES de la pile, vous avez perdu la référence et sa copie, c'est-à-dire qu'il y aura une erreur d'exécution de violation d'accès à un moment donné. Dans ce cas, vous avez besoin d'une copie complète de votre image en la clonant. De cette façon, vous pouvez récupérer les masques au cas où vous en auriez besoin à l'avenir.

EXAMPLE_OF_SHALLOW_COPY Je ne suis pas très bien informé par rapport aux utilisateurs de StackOverflow alors n'hésitez pas à supprimer cette partie et à mettre un bon exemple si vous pouvez clarifier. Mais je pense vraiment que ce n'est pas une bonne idée de faire une copie superficielle si vous savez que votre programme va fonctionner pendant une période de temps infinie, c'est-à-dire une opération "push-pop" continue sur la pile avec des appels de fonction. Si vous démontrez quelque chose à une personne amateur ou novice (par exemple, des trucs de tutoriel C / C ++), alors ça va probablement. Mais si vous exécutez une application telle que le système de surveillance et de détection ou le système de suivi du sonar, vous n'êtes pas censé continuer à copier vos objets en profondeur car cela tuera votre programme tôt ou tard.


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

char * ShallowCopy = Source;    

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

«ShallowCopy» pointe vers le même emplacement en mémoire que «Source». 'DeepCopy' pointe vers un emplacement différent dans la mémoire, mais le contenu est le même.


22

Qu'est-ce que la copie superficielle?

La copie superficielle est une copie bit à bit d'un objet. Un nouvel objet est créé qui a une copie exacte des valeurs de l'objet d'origine. Si l'un des champs de l'objet fait référence à d'autres objets, seules les adresses de référence sont copiées, c'est-à-dire que seule l'adresse mémoire est copiée.Copie superficielle

Dans cette figure, les MainObject1champs ont field1de type int et ContainObject1de type ContainObject. Lorsque vous effectuez une copie superficielle de MainObject1, MainObject2est créé avec field2contenant la valeur copiée de field1et pointant toujours vers ContainObject1lui-même. Notez que puisque field1est de type primitif, sa valeur est copiée field2mais comme ContainedObject1c'est un objet, MainObject2pointe toujours vers ContainObject1. Ainsi, toutes les modifications apportées à ContainObject1in MainObject1seront reflétées dans MainObject2.

Maintenant, s'il s'agit d'une copie superficielle, voyons ce qu'est une copie profonde?

Qu'est-ce que Deep Copy?

Une copie complète copie tous les champs et crée des copies de la mémoire allouée dynamiquement pointées par les champs. Une copie complète se produit lorsqu'un objet est copié avec les objets auxquels il se réfère. Copie profonde

Dans cette figure, le MainObject1 a des champs field1de type int et ContainObject1de type ContainObject. Lorsque vous effectuez une copie complète de MainObject1, MainObject2est créé avec field2contenant la valeur copiée de field1et ContainObject2contenant la valeur copiée de ContainObject1. Notez que toute modification apportée à ContainObject1in MainObject1ne sera pas reflétée dans MainObject2.

bon article


ce n'est pas de votre faute bien que cet exemple se réfère à un field3qui, lorsqu'il est en mesure d'essayer de comprendre quelque chose d'aussi profond que ce problème, où se situe le n ° 3 dans cet exemple ContainObject2 ?
Robb_2015

16

Dans la programmation orientée objet, un type comprend une collection de champs membres. Ces champs peuvent être stockés soit par valeur, soit par référence (c'est-à-dire un pointeur vers une valeur).

Dans une copie superficielle, une nouvelle instance du type est créée et les valeurs sont copiées dans la nouvelle instance. Les pointeurs de référence sont également copiés tout comme les valeurs. Par conséquent, les références pointent vers les objets d'origine. Toutes les modifications apportées aux membres stockés par référence apparaissent à la fois dans l'original et dans la copie, car aucune copie n'a été effectuée de l'objet référencé.

Dans une copie complète, les champs qui sont stockés par valeur sont copiés comme précédemment, mais les pointeurs vers des objets stockés par référence ne sont pas copiés. Au lieu de cela, une copie complète est faite de l'objet référencé et un pointeur vers le nouvel objet est stocké. Toute modification apportée à ces objets référencés n'affectera pas les autres copies de l'objet.


12

«ShallowCopy» pointe vers le même emplacement en mémoire que «Source». 'DeepCopy' pointe vers un emplacement différent dans la mémoire, mais le contenu est le même.


C'est un peu trompeur. Une copie superficielle et profonde copiera l'objet vers un nouvel emplacement en mémoire, une copie profonde copiera également les objets enfants tandis qu'une superficielle aura juste les nouveaux objets se référant aux anciens enfants. C'est difficile à lire sans se référer à l'objet d'origine.
Bill K

10

Clonage peu profond:
Définition: "Une copie superficielle d'un objet copie l'objet" principal ", mais ne copie pas les objets internes." Lorsqu'un objet personnalisé (par exemple, un employé) n'a que des variables de type chaîne primitives, vous utilisez le clonage superficiel.

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

Vous revenez super.clone();dans la méthode clone () substituée et votre travail est terminé.

Clonage profond :
Définition: "Contrairement à la copie superficielle, une copie profonde est une copie entièrement indépendante d'un objet."
Signifie lorsqu'un objet Employee contient un autre objet personnalisé:

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

Ensuite, vous devez également écrire le code pour cloner l'objet 'Adresse' dans la méthode clone () substituée. Sinon, l'objet Address ne sera pas cloné et il provoquera un bogue lorsque vous modifiez la valeur de Address dans l'objet Employee cloné, qui reflète également l'original.


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

Ce n'est pas un bon exemple. Les copies superficielles sont principalement utilisées pour la copie rapide d'objets, sans copier les données, mais une fois qu'un objet doit modifier les données partagées, une copie complète de celles-ci est prise. Votre exemple déroutera probablement les débutants.
CMircea

cela ne fonctionne que dans les langues qui utilisent des pointeurs pour représenter des chaînes. Le point que DHA essaie de faire valoir est que la copie superficielle ne fait que dupliquer les pointeurs vers le contenu d'origine identique (singulier), tandis que la copie profonde clone également le contenu référencé des pointeurs. Les deux méthodes copient le contenu de la surface. Si le langage stocke des chaînes en tant que contenu littéral de surface, par exemple à l'intérieur d'un en-tête WAV, cet exemple ne fonctionnera pas. Notez que cela est probablement trop difficile pour la plupart des problèmes de la vie réelle qui ne sont pas ésotériques.
DragonLord

8

Copie profonde

Une copie complète copie tous les champs et crée des copies de la mémoire allouée dynamiquement pointées par les champs. Une copie complète se produit lorsqu'un objet est copié avec les objets auxquels il se réfère.

Copie superficielle

La copie superficielle est une copie bit à bit d'un objet. Un nouvel objet est créé qui a une copie exacte des valeurs de l'objet d'origine. Si l'un des champs de l'objet fait référence à d'autres objets, seules les adresses de référence sont copiées, c'est-à-dire que seule l'adresse mémoire est copiée.


Ce lien ne fonctionne malheureusement plus - il renvoie maintenant à un article de février 2019 concernant la conception de sites Web (sauf si l'auteur est clairvoyant?).
PhilPhil

7

Copie superficielle - La variable de référence à l'intérieur des objets originaux et copiés peu profonds fait référence à un objet commun .

Copie profonde - La variable de référence à l'intérieur des objets originaux et copiés en profondeur fait référence à un objet différent .

clone fait toujours une copie superficielle.

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

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

} 

Les résultats ci-dessus seront-

faux vrai vrai

faux faux faux

Tout changement apporté à un objet d'origine se reflétera dans un objet peu profond et non dans un objet profond.

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

Output- Visualbasic C


7

Je voudrais donner un exemple plutôt que la définition formelle.

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

Ce code montre une copie superficielle :

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

Ce code montre une copie complète :

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

Je reçois1 1 4 4 4 4 4 4
Suresh Prajapati

en copie profonde, faites copyObject.a = 8 puis vérifiez. j'espère que vous obtiendrez une réponse appropriée.
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

En termes simples, une copie superficielle est similaire à l'appel par référence et une copie approfondie est similaire à l'appel par valeur

Dans Appel par référence, les paramètres formels et réels d'une fonction font référence au même emplacement de mémoire et à la valeur.

Dans Appel par valeur, les paramètres formels et réels d'une fonction font référence à un emplacement de mémoire différent mais ayant la même valeur.


5

Imaginez qu'il existe deux tableaux appelés arr1 et arr2.

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

5

Une copie superficielle construit un nouvel objet composé et y insère ses références à l'objet d'origine.

Contrairement à la copie superficielle, la copie profonde construit un nouvel objet composé et insère également des copies des objets d'origine de l'objet composé d'origine.

Prenons un exemple.

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

Le code ci-dessus imprime FAUX.

Voyons comment.

Objet composé d'origine x=[1,[2]](appelé composé car il contient un objet à l'intérieur de l'objet (Inception))

entrez la description de l'image ici

comme vous pouvez le voir sur l'image, il y a une liste à l'intérieur de la liste.

Ensuite, nous en créons une copie superficielle à l'aide de y = copy.copy(x). Ce que python fait ici, c'est qu'il créera un nouvel objet composé, mais les objets à l'intérieur d'eux pointent vers les objets d'origine.

entrez la description de l'image ici

Dans l'image, il a créé une nouvelle copie pour la liste externe. mais la liste intérieure reste la même que celle d'origine.

Nous en créons maintenant une copie profonde à l'aide de z = copy.deepcopy(x). ce que python fait ici, c'est qu'il créera un nouvel objet pour la liste externe ainsi que la liste interne. comme indiqué dans l'image ci-dessous (surligné en rouge).

entrez la description de l'image ici

À la fin, le code s'imprime False, car y et z ne sont pas les mêmes objets.

HTH.


2

La copie superficielle crée un nouvel objet, puis copie les champs non statiques de l'objet actuel vers le nouvel objet. Si un champ est un type de valeur -> une copie bit par bit du champ est effectuée; pour un type de référence -> la référence est copiée mais l'objet référencé ne l'est pas; par conséquent, l'objet d'origine et son clone font référence au même objet.

La copie profonde crée un nouvel objet, puis copie les champs non statiques de l'objet actuel vers le nouvel objet. Si un champ est un type de valeur -> une copie bit par bit du champ est effectuée. Si un champ est un type de référence -> une nouvelle copie de l'objet référencé est effectuée. Les classes à cloner doivent être marquées comme [Sérialisable].


2

Tiré de [blog]: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

La copie profonde implique l'utilisation du contenu d'un objet pour créer une autre instance de la même classe. Dans une copie complète, les deux objets peuvent contenir les mêmes informations mais l'objet cible aura ses propres tampons et ressources. la destruction de l'un ou l'autre objet n'affectera pas l'objet restant. L'opérateur d'affectation surchargé créerait une copie complète des objets.

La copie superficielle implique la copie du contenu d'un objet dans une autre instance de la même classe, créant ainsi une image miroir. En raison de la copie directe des références et des pointeurs, les deux objets partageront le même contenu contenu en externe de l'autre objet pour être imprévisible.

Explication:

En utilisant un constructeur de copie, nous copions simplement les valeurs de données membre par membre. Cette méthode de copie est appelée copie superficielle. Si l'objet est une classe simple, composée de types intégrés et sans pointeurs, cela serait acceptable. Cette fonction utiliserait les valeurs et les objets et son comportement ne serait pas modifié avec une copie superficielle, seules les adresses des pointeurs qui sont membres sont copiées et non la valeur vers laquelle pointe l'adresse. Les valeurs de données de l'objet seraient alors modifiées par inadvertance par la fonction. Lorsque la fonction sort de la portée, la copie de l'objet avec toutes ses données est extraite de la pile.

Si l'objet a des pointeurs, une copie complète doit être exécutée. Avec la copie en profondeur d'un objet, la mémoire est allouée à l'objet en magasin gratuit et les éléments pointés sont copiés. Une copie complète est utilisée pour les objets renvoyés par une fonction.


2

Pour ajouter plus à d'autres réponses,

  • une copie superficielle d'un objet effectue une copie par valeur pour les propriétés basées sur les types de valeur et une copie par référence pour les propriétés basées sur les types de référence.
  • une copie profonde d'un objet effectue une copie par valeur pour les propriétés basées sur les types de valeur, ainsi qu'une copie par valeur pour les propriétés basées sur les types de référence profondément dans la hiérarchie (des types de référence)

2

La copie superficielle ne créera pas de nouvelle référence mais la copie profonde créera la nouvelle référence.

Voici le programme pour expliquer la copie profonde et peu profonde.

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

Copier des araries:

Array est une classe, ce qui signifie qu'il s'agit d'un type de référence, donc array1 = array2 entraîne deux variables qui référencent le même tableau.

Mais regardez cet exemple:

  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 superficiel signifie que seule la mémoire représentée par le tableau cloné est copiée.

Si le tableau contient des objets de type valeur, les valeurs sont copiées ;

si le tableau contient un type de référence, seules les références sont copiées. Par conséquent, il existe deux tableaux dont les membres font référence aux mêmes objets .

Pour créer une copie complète - où le type de référence est dupliqué, vous devez parcourir le tableau et cloner chaque élément manuellement.


Je ne connais pas les autres langages, mais en C # / VB, la copie superficielle d'un tableau de types de valeurs ne copie pas les valeurs. Les deux tableaux font référence aux mêmes objets. Ajoutez un bouton à un formulaire et ajoutez ce code pour voir: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

vous avez raison, j'ai corrigé ma réponse pour être plus précis, en utilisant clone sur des tableaux. Vous avez tout à fait raison de dire que «la copie superficielle d'un tableau de types de valeurs ne copie pas les valeurs», mais l'utilisation de clone sur le tableau le fait. J'ai essayé d'expliquer cela, essayez-le. Merci
lukaszk

1

Je suis venu à comprendre des lignes suivantes.

La copie superficielle copie les champs d' un type de valeur d' objet (int, float, bool) dans l'objet cible et les types de référence d'objet (chaîne, classe, etc.) sont copiés en tant que références dans l'objet cible. Dans cette référence, les types de référence pointeront vers l'emplacement mémoire de l'objet source.

La copie approfondie copie les types de valeur et de référence d'un objet dans une nouvelle copie complète des objets cibles. Cela signifie que les types de valeur et les types de référence se verront attribuer de nouveaux emplacements de mémoire.


0

Ajoutant à toutes les définitions ci-dessus, une copie approfondie de plus et la plus couramment utilisée, se trouve dans le constructeur de copie (ou opérateur d'affectation de surcharge) de la classe.

Copie superficielle -> est lorsque vous ne fournissez pas de constructeur de copie. Ici, seul l'objet est copié mais pas tous les membres de la classe sont copiés.

Copie profonde -> est lorsque vous avez décidé d'implémenter le constructeur de copie ou l'affectation de surcharge dans votre classe et permet de copier tous les membres de la 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

Le constructeur de copie est utilisé pour initialiser le nouvel objet avec l'objet précédemment créé de la même classe. Par défaut, le compilateur a écrit une copie superficielle. La copie superficielle fonctionne correctement lorsque l'allocation de mémoire dynamique n'est pas impliquée, car lorsque l'allocation de mémoire dynamique est impliquée, les deux objets pointeront vers le même emplacement de mémoire dans un tas.Par conséquent, pour supprimer ce problème, nous avons écrit une copie approfondie afin que les deux objets aient leur propre copie d'attributs dans une mémoire. Afin de lire les détails avec des exemples et des explications complets, vous pouvez voir l'article Constructeurs C ++ .

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.