La réponse générale a déjà été fournie par d'autres, y compris @ x13n. Je vais essayer de fournir une explication un peu plus détaillée de ce que le code signifie vraiment.
La syntaxe MyObject ob = anotherMyObject;
est équivalente à MyObject obj(anotherMyObject);
. La signification est copie construire ob
de l'objet anotherMyObject
. Le compilateur correspondra toujours MyObject ob = ...;
avec un appel au constructeur de copie (habituellement MyObject(MyObject const &)
, mais peut également être MyObject(MyObject&)
si l'utilisateur le déclare comme tel).
Dans votre code, le côté droit n'est pas un MyObject
, donc il ne peut pas être passé comme argument au constructeur de copie et le compilateur essayera de convertir ce rhs en quelque chose qui peut être utilisé avec le constructeur de copie de MyObject
en appliquant les règles générales. Dans votre cas, il est un constructeur implicite qui prend un argument int
, et qui peut être utilisé pour créer un MyObject
temporaire, de sorte que le compilateur réécrit votre code pour être:
MyObject ob(MyObject(99));
// ^^^ temporary created by the compiler to match the copy constructor
Notez que ce n'est pas la même chose que MyObject ob(99)
, mais une combinaison des constructeurs int
et de copie, même si l'effet global est similaire. Si le constructeur prenant un nombre entier a été déclaré explicit
, le compilateur n'a pas pu l'utiliser pour fournir la conversion et le code échouerait à compiler.
Dans un commentaire à une autre réponse @ x13n indique qu'il ne s'agit pas d'un appel au constructeur de copie, comme si vous ajoutiez une trace à ce constructeur, la trace ne sera pas générée. C'est un problème complètement différent, où le compilateur est capable d'optimiser la copie en créant le temporaire dans exactement la même adresse que prend ob
. Il y a deux façons de vérifier cela, toutes deux dépendant du fait que, bien que le compilateur puisse élider la copie, il doit respecter les mêmes restrictions. Nous pouvons donc MyObject ob(MyObject(99))
invalide de deux façons, soit désactiver l'accès au constructeur de copie ou de désactiver l'appel au constructeur avec un temporaire:
class test1 {
test1(test1 const &) {} // make the copy constructor private
public:
test1(int) {}
};
class test2 {
public:
test2(test2 &) {} // make the copy constructor take a non-const reference
// i.e. disable the use of temporaries
test2(int) {}
};
int main() {
test1 t1 = 99; // copy constructor is private in this context
test2 t2 = 99; // g++: no matching function call to test2::test2(test2)
// diagnostics will differ with other compilers
}
Non, il ne pas appeler constructeur de copie. Ajoutez 'MyClass (const MyClass & asdf): a (asdf.a) {cout <<" cc appel "<< endl;}' à son code. "cc appel" ne sera pas imprimé. – x13n
@ x13n vous avez raison, si j'aime bien cet obj MyClass (99); MyClass ob = obj; alors le constructeur de la copie sera appelé – anand
@ x13n: Vous avez tort et que @ Alien01 avait raison en premier lieu. Le langage spécifie que 'MyClass ob = 99' est équivalent à' MyClass ob (MyClass (99)) '. Autrement dit, le compilateur crée un temporaire avec le constructeur implicite et * puis * le copie dans l'objet réel. L'effet que vous voyez (manque de sortie de votre constructeur de copie) est dû à une optimisation, où le compilateur peut créer le temporaire au même endroit que l'objet résultant et donc élider la copie. Pour le vérifier, déclarez le constructeur de copie privé et vous obtiendrez une erreur d'accès dans le code. –