53 votes

Copie profonde et copie superficielle

Duplicata possible :
Quelle est la différence entre une copie profonde et une copie superficielle ?

Quelle est la différence entre une copie profonde et une copie superficielle ? Quel type de copie fait un constructeur de copie ?

53voto

stakx Points 29832

Copie superficielle :

Certains membres de la copie peuvent référencer les mêmes objets que l'original :

class X
{
private:
    int i;
    int *pi;
public:
    X()
        : pi(new int)
    { }
    X(const X& copy)   // <-- copy ctor
        : i(copy.i), pi(copy.pi)
    { }
};

Ici, le pi membre de l'original et de la copie X pointeront tous deux vers le même int .


Copie profonde :

Tous les membres de l'original sont clonés. Il n'y a pas d'objets partagés :

class X
{
private:
    int i;
    int *pi;
public:
    X()
        : pi(new int)
    { }
    X(const X& copy)   // <-- copy ctor
        : i(copy.i), pi(new int(*copy.pi))  // <-- note this line in particular!
    { }
};

Ici, le pi membre de l'original et de la copie X pointera vers différents int mais ces deux objets ont la même valeur.


Le constructeur de copie par défaut (qui est automatiquement fourni si vous n'en fournissez pas un vous-même) ne crée que des copies superficielles.


P.S. : Juste à titre de référence : Voici ce que dit la section 12.8, paragraphe 8 de la norme C++ de 1998 à propos des exemples de code ci-dessus :

La copie implicitement définie défini implicitement pour la classe X effectue une copie membre par membre de ses sous-objets. [...] Chaque sous-objet est copié de la manière appropriée à son type : [...]. manière appropriée à son type : [...] [S]i le sous-objet est de type scalaire, l'opérateur d'affectation intégré est est utilisé.

12voto

cletus Points 276888

L'exemple le plus typique est un tableau de pointeurs vers des structures ou des objets (qui sont mutables).

A copie superficielle copie le tableau et maintient les références aux objets d'origine.

A copie profonde copiera (clonera) également les objets, de sorte qu'ils n'auront aucune relation avec l'original. Implicitement, les objets eux-mêmes sont copiés en profondeur. C'est là que les choses se compliquent, car il n'y a pas de véritable moyen de savoir si un objet a été copié en profondeur ou non.

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 peu profonde. La copie superficielle fonctionne bien lorsque l'allocation dynamique de la mémoire n'est pas impliquée, car lorsque l'allocation dynamique de la mémoire est impliquée, les deux objets pointeront vers le même emplacement de mémoire dans un tas. Par conséquent, pour éliminer ce problème, nous avons écrit une copie profonde afin que les deux objets aient leur propre copie des attributs dans une mémoire.

Pour lire les détails avec des exemples et des explications complètes, vous pouvez consulter l'article suivant Constructeurs et destructeurs .

Le constructeur de copie par défaut est peu profond. Vous pouvez rendre vos propres constructeurs de copie profonds ou superficiels, selon le cas. Voir Notes sur le C++ : LA POO : Copie des constructeurs .

3voto

n535 Points 2558

La copie profonde effectue littéralement une copie profonde. Cela signifie que si votre classe possède des champs qui sont des références, ce sont leurs valeurs qui seront copiées, et non les références elles-mêmes. Si, par exemple, vous avez deux instances d'une classe, A et B avec des champs de type référence, et que vous effectuez une copie profonde, le changement de la valeur de ce champ dans A n'affectera pas la valeur dans B. Et vice-versa. Les choses sont différentes avec la copie superficielle, parce que seules les références sont copiées, donc, changer ce champ dans un objet copié affecterait l'objet original.

Quel type de copie fait un constructeur de copie ?

Cela dépend de la mise en œuvre. Cela signifie qu'il n'y a pas de règles strictes à ce sujet, vous pouvez l'implémenter comme une copie profonde ou une copie superficielle, cependant pour autant que je sache, il est courant d'implémenter une copie profonde dans un constructeur de copie. Un constructeur de copie par défaut effectue cependant une copie superficielle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X