Partager via


Constructeurs de copie et opérateurs d’assignation de copie (C++)

Remarque

À partir de C++11, deux types d’assignations sont pris en charge dans le langage : assignation de copie et assignation de déplacement. Dans cet article « assignation » signifie assignation de copie, sauf spécification contraire. Pour plus d’informations sur l’assignation de déplacement, consultez Constructeurs de déplacement et opérateurs d’assignation de déplacement (C++).

Les opérations d'assignation et d'initialisation génèrent une copie des objets.

  • Assignation : lorsque la valeur d’un objet est affectée à un autre objet, le premier objet est copié dans le deuxième objet. Par conséquent, ce code copie la valeur de b dans a :

    Point a, b;
    ...
    a = b;
    
  • initialisation : l’initialisation se produit lorsque vous déclarez un nouvel objet, lorsque vous passez des arguments de fonction par valeur ou lorsque vous retournez par valeur à partir d’une fonction.

Vous pouvez définir la sémantique de « copie » pour les objets de type classe. Considérez par exemple le code suivant :

TextFile a, b;
a.Open( "FILE1.DAT" );
b.Open( "FILE2.DAT" );
b = a;

Ce code pourrait signifier « copier le contenu de FILE1.DAT vers FILE2.DAT » ou « ignorer FILE2.DAT et faire de b un deuxième handle vers FILE1.DAT ». Vous devez lier à chaque classe la sémantique de copie appropriée, comme suit :

  • Utilisez un opérateur d’affectation operator= qui retourne une référence au type de classe et accepte un paramètre passé par const référence—par exemple ClassName& operator=(const ClassName& x);.

  • Utilisez le constructeur de copie.

Si vous ne déclarez pas de constructeur de copie, le compilateur génère un constructeur de copie de membre à membre à votre place. De même, si vous ne déclarez pas d’opérateur d’assignation de copie, le compilateur génère un opérateur d’assignation de copie de membre à membre à votre place. La déclaration d’un constructeur de copie n’entraîne pas la suppression de l’opérateur d’assignation de copie généré par le compilateur, et vice versa. Si vous implémentez l’une ou l’autre, nous vous recommandons également d’implémenter l’autre. Lorsque vous implémentez les deux, la signification du code est claire.

Le constructeur de copie utilise un argument de type , ClassName&ClassName est le nom de la classe. Par exemple :

// spec1_copying_class_objects.cpp
class Window
{
public:
    Window( const Window& );            // Declare copy constructor.
    Window& operator=(const Window& x); // Declare copy assignment.
    // ...
};

int main()
{
}

Remarque

Utilisez le type d’argument pour le constructeur de copie const ClassName&chaque fois que c’est possible. Cela empêche le constructeur de copie de modifier accidentellement l’objet copié. Il vous permet également de copier à partir de const objets.

Constructeurs de copie générés par le compilateur

Les constructeurs de copie générés par le compilateur, comme les constructeurs de copie définis par l’utilisateur(-trice), ont un seul argument de type « référence à class-name ». Toutefois, cette règle ne se vérifie pas lorsque toutes les classes de base et les classes de membre possèdent des constructeurs de copie déclarés comme prenant un argument unique de type const class-name&. Dans ce cas, l’argument du constructeur de copie généré par le compilateur est également const.

Lorsque le type d’argument du constructeur de copie n’est pas const, l’initialisation via la copie d’un objet const génère une erreur. L’inverse est impossible : si l’argument est const, vous pouvez initialiser en copiant un objet qui n’est pas const.

Les opérateurs d’assignation générés par le compilateur suivent le même modèle pour const. Ils acceptent un argument unique de type ClassName& à moins que les opérateurs d’assignation dans toutes les classes de base et les classes de membre n’acceptent des arguments du type const ClassName&. Dans ce cas, l’opérateur d’assignation généré pour la classe prend un argument const.

Remarque

Lorsque des classes de base virtuelles sont initialisées par des constructeurs de copie, qu’ils soit générés par le compilateur ou définis par l’utilisateur(-trice), elles ne sont initialisées qu’une seule fois : au moment où elles sont construites.

Les conséquences sont semblables au constructeur de copie. Lorsque le type d’argument n’est pas const, l’assignation d’un objet const génère une erreur. L’inverse n’est pas vrai : si une valeur const est affectée à une valeur qui n’est pas const, l’assignation réussit.

Pour plus d’informations sur les opérateurs d’assignation surchargés, consultez Assignation.