Constructeur de copie

Décembre 2016

Constructeur de copie

Le compilateur ne génère pas seulement un constructeur et un destructeur par défaut si l’utilisateur ne les a pas définis, il génère aussi un constructeur de copie qui est appelé chaque fois qu’une copie d’objet est réalisée en mémoire.

Ce constructeur par défaut recopie simplement toutes les données membres de l’objet initial transmises en arguments comme données membres du nouvel objet.

Une copie d’objet est réalisée chaque fois que vous transmettez un objet par valeur à une fonction, ou lorsqu’une fonction retourne un objet de la même façon.

Le constructeur de copie par défaut n’est pas toujours suffisant, il est quelquefois nécessaire de le fournir explicitement. En effet, dans le cas de références ou de pointeurs, ce n’est pas la valeur de la donnée membre elle-même qui sera recopiée mais la valeur du pointeur sur cette donnée.

Le constructeur réalise une copie logique (voir fig. 4.1) et les deux objets pointent sur les mêmes emplacements en mémoire.

Figure 4.1 : copie d’un objet à l’aide du constructeur de copie par défaut.

Le problème apparaît si les valeurs de l’objet initial sont modifiées ou si cet objet disparaît.

Dans ce dernier cas, le destructeur libère les ressources allouées, il va donc effacer les valeurs des données membres stockées en mémoire, et les pointeurs associés aux données membres de l’objet copié ne correspondront plus à rien.

Dans le premier cas, la modification de la valeur des données membres sera répercutée sur les données membres de l’objet copié, ce qui ne sera pas forcément l’effet recherché.

Le code 4.7 illustre l’utilisation d’un constructeur de copie.

Code 4.7 : utilisation d’un constructeur de copie (fichier en-tête Date.h)

#include<iostream>      //Pour les entrées/sorties   
using namespace std;   
    
class Date   
{   
private:   
   int *jour, *mois, *annee;   
public:   
   Date(int,int,int);          //Constructeur par défaut   
   Date (const Date &);        //constructeur de copie   
   ~Date();                    //Destructeur   

   /* Méthodes d’accès */   
   void DefinirDate(int j,int m,int a)   
   { *jour=j;  *mois=m;  *annee=a; }   
   void LireDate() const    
   { cout<<*jour<<" "<<*mois<<" "<<*annee<<endl; }   
   int LireJour() const { return *jour; }   
   int LireMois() const { return *mois; }   
   int LireAnnee() const { return *annee; }   
};  

Code 4.8 : utilisation d’un constructeur de copie (fichier source Date.cpp)

#include"Date.h"   //Inclusion de la déclaration de Date   

/****Définition du constructeur****/   
Date::Date(int j,int m,int a)   
{   
/*réservation de l’espace mémoire dans le tas, les valeurs des membres sont ensuite stockées aux adresses correspondantes*/   
   jour=new int; *jour=j;    
   mois=new int; *mois=m;    
   annee=new int; *annee=a;  //   
}   

/****Définition du constructeur de copie***/   
Date::Date(const Date &source)  //l’objet source est protégé par const   
{   
/*réservation de l’espace mémoire dans le tas puis copie des valeurs aux adresses correspondantes*/   
   jour=new int;  *jour=source.LireJour();    
   mois=new int;  *mois=source.LireMois();    
   annee=new int; *annee=source.LireAnnee();    
}   

/****Définition du destructeur****/   
Date::~Date()    
{   
   delete jour;  jour=0;   //libération de la mémoire   
   delete mois;  mois=0;   
   delete annee; annee=0;   
}   

int main()   
{   
   cout << "\nNous créons l’objet Date_initiale= 1 1 2009 ";   
   Date Date_initiale(1,1,2009);   
   cout << "\nNous le copions dans l’objet Copie_date ";   
   Date Copie_date=Date_initiale ;   
   //équivalent à Date Copie_date(Date_initiale);   

   cout << "\nNous changeons maintenant Date_initiale en 31 12 2010 " << endl;   
//modification de l’objet initial :   
   Date_initiale.DefinirDate(31,12,2010);   
   cout << "Nous obtenons les deux objets : \n" ;   
   cout << "Date_initiale = ";   
     Date_initiale.LireDate();   
   cout << "Alors que Copie_date a toujours la valeur: ";   
   Copie_date.LireDate();   
   cout << "\nCQFD" << endl;   
} 


Vous obtenez :

Nous créons l’objet Date_initiale= 1 1 2009    
Nous le copions dans l’objet Copie_date   
Nous changeons maintenant Date_initiale en 31 12 2010   
Nous obtenons les deux objets :   
Date_initiale = 31 12 2010   
Alors que Copie_date a toujours la valeur: 1 1 2009   
CQFD


Le texte original de cette fiche pratique est extrait de
«Tout sur le C++» (Christine EBERHARDT, Collection
CommentCaMarche.net, Dunod, 2009)

A voir également :

Ce document intitulé «  Constructeur de copie  » issu de CommentCaMarche (www.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.