Dans quelles situations le C++ constructeur de copie appelé?
Je sais que les situations suivantes en c++ où le constructeur de copie serait invoquée:
-
lorsqu'un objet est attribuée à un objet de sa propre classe
MyClass A,B; A = new MyClass(); B=A; //copy constructor called
-
si une des fonctions reçoit comme argument, passé par valeur, un objet d'une classe
void foo(MyClass a); foo(a); //copy constructor invoked
-
lorsqu'une fonction retourne (en valeur) d'un objet de la classe
MyClass foo () { MyClass temp; .... return temp; //copy constructor called }
N'hésitez pas à corriger les éventuelles erreurs que j'ai fait; mais je suis plus curieux de savoir si il y a d'autres situations dans lesquelles le constructeur de copie est appelé.
- J'ai pensé
A=B;
appelle la copie opérateur d'affectation. - Lire aussi à propos de la valeur de retour d'optimisation (RVO), votre dernier exemple, pourrait ne pas copier quoi que ce soit.
- En outre,
A = new MyClass();
ne compile pas. - Ce n'est pas valide en C++.
- seulement c'est fait après la déclaration de
A
. Par exemple:A a; ... a=b;
. Si c'est fait à la déclaration elle-même, puisA a=b
est équivalent àA a(b)
. - intéressant. Je suppose que ça ne ferait pas de sens de le construire, de le supprimer, puis de le copier.
- J'ai roulé en arrière à la version précédente de la question parce que les réponses et les commentaires ont été basés sur elle.
- En fait,
A a = b;
est équivalent àA a(A(b));
si je me souviens bien, et a donc besoin d'une copie accessible constructeur sur le dessus d'une conversion implicite. - Excusez-moi, mais votre java est à l'affiche.
- Prowl ne pourrait-elle pas compiler si
MyClass
avait une surcharge de l'opérateur d'affectation de la prise d'unMyClass*
comme argument? - Ah, nice (ou plutôt moche!) 😉 Oui, il serait, cependant il n'y a pas de raison de considérer que la possibilité ici, comme l'OP est surtout concerné par les principes de base de la copie et de l'affectation. Mais oui, votre observation est correcte.
- double possible de C++ constructeur de copie comportement
Vous devez vous connecter pour publier un commentaire.
J'ai peut-être tort, mais cette classe permet de voir ce qui est appelé et quand:
Alors ce code:
produit ce que le résultat:
Une autre chose intéressante, disons que vous avez le code suivant:
Ce problème se produit car lorsque vous lorsque vous affectez un pointeur, qui ne fait rien à l'objet réel.
a c = b;
également les appels de constructeur de copiec = a + b;
c
est déjà déclaré, et la surcharge de l'opérateur+ est le retour de l'objet par valeur. Qui seront appelés? copie de la cession ou de constructeur de copie ou les deux. Je suis confus.Pas nécessairement. Ce type de cession est appelé copie de cession, sens de l'opérateur d'affectation de la classe sera appelée à effectuer memberwise cession de tous les membres de données. La fonction réelle est
MyClass& operator=(MyClass const&)
Le constructeur par copie n'est pas évoquée ici. C'est parce que l'opérateur d'affectation prend en référence à son objet, et donc pas de copier-construction est effectuée.
Copie d'affectation est différente de copier-initialisation parce que la copie de l'initialisation se fait uniquement lorsqu'un objet est initialisé. Par exemple:
La première expression initialise
y
en copiantx
. Il appelle le constructeur par copieMyClass(MyClass const&)
.Et comme mentionné,
x = y
est un appel à l'opérateur d'affectation.(Il y a aussi quelque chose appelé copier-elison lequel le compilateur va éluder les appels au constructeur par copie. Le compilateur est plus que probable utilise ce).
C'est correct. Cependant, notez que dans C++11 si
a
est une value et siMyClass
a le constructeur appropriéMyClass(MyClass&&)
,a
peut être déplacé dans le paramètre.(Le constructeur par copie et le déplacement-constructeur sont deux de la valeur par défaut généré par le compilateur fonctions membres d'une classe. Si vous ne fournissez pas vous-même, le compilateur va généreusement le faire pour vous à des circonstances spécifiques).
Par de retour de la valeur de l'optimisation, comme mentionné dans la réponse, le compilateur peut supprimer l'appel au constructeur par copie. En utilisant l'option de compilateur
-fno-éluder-constructeurs
, vous pouvez désactiver la copie elison et de voir que le constructeur par copie serait en effet être appelé dans ces situations.-fno-elide-constructors
n'est pas activé, alors c'est en fait le déplacez-constructeur qui est appelé en premier, s'il est disponible, et si ce n'est le constructeur par copie est appelée. La raisonMyClass& ref=temp; return ref
appelle le constructeur par copie est parce que la valeur de retour d'optimisation nécessite un id-expression. Vous auriez besoin d'un explicitestd::move
dans ce cas.Situation (1) est incorrect et ne compile pas la manière que vous avez écrit. Il doit être:
Vous sont correcte dans le cas (2).
Mais dans le cas (3), le constructeur de copie ne peut pas être appelé: si le compilateur ne peut pas constaté d'effets secondaires, alors il peut mettre en œuvre retour optimisation de la valeur pour optimiser les inutiles copie en profondeur. C++11 formalise cette avec références rvalue.
Ce est correct à la base (autre que votre erreur de frappe dans la #1).
Un scénario spécifique à surveiller lorsque vous avez des éléments dans un conteneur, les éléments peuvent être copiés à divers moments (par exemple, dans un vecteur, lorsque le vecteur de croissance et certains éléments sont supprimés). C'est en fait juste un exemple de #1, mais il peut être facile d'oublier.
Il y a 3 situations dans lesquelles le constructeur de copie est appelé:
Lorsque nous de faire une copie d'un objet.
Quand on passe d'un objet comme un argument par valeur à une méthode.
Lorsque nous retourner un objet à partir d'une méthode par valeur.
ce sont les seules situations....je pense que...
Voici le cas lorsque le constructeur de copie est appelé.
D'autres ont donné de bonnes réponses, avec des explications et des références.
En outre, j'ai écrit une classe de vérifier les différents types de instantations/assignations (C++11 prêt), dans un essai complet:
Voici le test:
Ceci est un extrait de l'essai compilé avec
GCC 4.8.2
avec-O3
et-fno-elide-constructors
drapeaux:Enfin le même test avec copie élision activé:
Ici est le code complet de l'exécution à ideone.