Quelle est la différence entre une copie profonde et une copie peu profonde?
language-agnostic
copy
deep-copy
shallow-copy
David Locke
la source
la source
Réponses:
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.
la source
Largeur vs profondeur; pensez en termes d'arbre de références avec votre objet comme nœud racine.
Peu profond:
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:
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é.
la source
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
la source
Essayez de considérer l'image suivante
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
la source
Surtout pour les développeurs iOS:
Si
B
est une copie superficielle deA
, alors pour les données primitives c'est commeB = [A assign];
et pour les objets c'est commeB = [A retain]
;B et A pointent vers le même emplacement mémoire
Si
B
c'est une copie complète deA
, 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
la source
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:
la source
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.
la source
Par souci de simplicité, vous pouvez suivre cet article: https://www.cs.utexas.edu/~scottm/cs307/handouts/deepCopying.htm
Copie superficielle:
Copie profonde:
la source
{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.
la 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.
la source
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.
Dans cette figure, les
MainObject1
champs ontfield1
de type int etContainObject1
de typeContainObject
. Lorsque vous effectuez une copie superficielle deMainObject1
,MainObject2
est créé avecfield2
contenant la valeur copiée defield1
et pointant toujours versContainObject1
lui-même. Notez que puisquefield1
est de type primitif, sa valeur est copiéefield2
mais commeContainedObject1
c'est un objet,MainObject2
pointe toujours versContainObject1
. Ainsi, toutes les modifications apportées àContainObject1
inMainObject1
seront reflétées dansMainObject2
.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.
Dans cette figure, le MainObject1 a des champs
field1
de type int etContainObject1
de typeContainObject
. Lorsque vous effectuez une copie complète deMainObject1
,MainObject2
est créé avecfield2
contenant la valeur copiée defield1
etContainObject2
contenant la valeur copiée deContainObject1
. Notez que toute modification apportée àContainObject1
inMainObject1
ne sera pas reflétée dansMainObject2
.bon article
la source
field3
qui, 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 exempleContainObject2
?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.
la 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.
la source
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.
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é:
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.
la source
la source
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.
la source
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 .
la classe principale suit-
Les résultats ci-dessus seront-
Tout changement apporté à un objet d'origine se reflétera dans un objet peu profond et non dans un objet profond.
Output- Visualbasic C
la source
Je voudrais donner un exemple plutôt que la définition formelle.
Ce code montre une copie superficielle :
Ce code montre une copie complète :
la source
1 1 4 4 4 4 4 4
la source
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.
la source
Imaginez qu'il existe deux tableaux appelés arr1 et arr2.
la source
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.
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))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.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).À la fin, le code s'imprime
False
, car y et z ne sont pas les mêmes objets.HTH.
la source
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].
la source
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.
la source
Pour ajouter plus à d'autres réponses,
la source
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.
la source
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:
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.
la source
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]); }
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.
la source
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.
la source
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 ++ .
la source