Pourquoi utiliser des références aux paramètres du constructeur de copie?

J'ai trouvé beaucoup d'informations disant que c'était pour éviter les appels illimités, mais je ne comprends toujours pas.

6
yellow-monkey 2 avril 2020 à 12:01

3 réponses

Meilleure réponse

Lorsque vous passez à une méthode par valeur, une copie est faite de l'argument. La copie utilise le constructeur de copie, donc vous obtenez une situation de poule et d'oeuf avec des appels récursifs infinis au constructeur de copie.

Réponse au commentaire:

Le passage par référence ne permet pas de faire passer une copie de l'objet. Il passe simplement l'adresse de l'objet (cachée derrière la syntaxe de référence) de sorte que l'objet à l'intérieur du constructeur de copie (ou toute méthode à laquelle un objet est passé par référence) est le même objet que celui à l'extérieur.

En plus de résoudre le problème de la poule et de l'œuf ici, le passage par référence est généralement (pour les objets plus gros - plus gros que la taille d'un point) plus rapide.

Réponse à un autre commentaire:

Vous pouvez écrire une sorte de constructeur de copie qui passe par un pointeur, et cela fonctionnerait de la même manière que le passage par référence. Mais il serait fastidieux d'appeler explicitement et impossible d'appeler implicitement.

Déclaration:

class X
{
public:
    X();
    X(const X* const pOther);
};

La copie explicite:

X x1;

X x2(&x1);  // Have to take address

La copie implicite:

void foo (X copyOfX);   // Pass by value, copy made

...

X x1;

foo (x1);  // Copy constructor called implicitly if correctly declared
           // But not matched if declared with pointer

foo (&x1); // Copy construcxtor with pointer might (?) be matched
           // But function call to foo isn't

En fin de compte, une telle chose ne serait pas considérée comme un constructeur de copie C ++.

7
Ardent Coder 4 avril 2020 à 10:43

De cette page Web

Un constructeur de copie est appelé lorsqu'un objet est passé par valeur. Le constructeur de copie lui-même est une fonction. Donc, si nous passons un argument par valeur dans un constructeur de copie, un appel au constructeur de copie serait fait pour appeler le constructeur de copie qui devient une chaîne d'appels sans terminaison. Par conséquent, le compilateur n'autorise pas la transmission de paramètres par valeur.

En passant l'argument par valeur, le constructeur de copie s'appelle lui-même, entrant dans un «cycle de récursion» infini. Le lien ci-dessus explique assez bien les sujets de base sur le constructeur de copie.

1
Eddymage 2 avril 2020 à 09:25

Ce code:

class MyClass {
public:
  MyClass();
  MyClass(MyClass c);
};

Ne compile pas. Autrement dit, parce que la deuxième ligne ici:

MyClass a;
MyClass b(a);

Devrait théoriquement provoquer la boucle infinie dont vous parlez - il devrait construire une copie de a avant d'appeler le constructeur pour b. Cependant, si le constructeur de copie ressemble à ceci:

  MyClass(const MyClass& c);

Ensuite, aucune copie n'est requise avant d'appeler le constructeur de copie.

5
NadavS 2 avril 2020 à 09:09