Pourquoi l'argument du constructeur de copie d'une référence plutôt qu'un pointeur?
Pourquoi l'argument du constructeur de copie d'une référence plutôt qu'un pointeur?
Pourquoi ne peut-on pas utiliser le pointeur à la place?
6 réponses
il y a plusieurs raisons:
les références ne peuvent être nulles. OK, il est possible de créer une référence nulle, mais il est aussi possible de lancer un
std::vector<int>*
dans unstd::vector<SomeType>*
. Ça ne veut pas dire qu'un tel casting a un comportement défini. Et créer une référence nulle non plus. Les pointeurs ont un comportement défini lorsqu'ils sont définis à NULL; les références ne le font pas. Les références sont donc toujours prévu pour désigner des objets réels.les Variables et les temporairesne peuvent pas être implicitement converti en pointeurs de leurs types. Pour des raisons évidentes. Nous ne voulons pas de pointeurs vers des temporairesqui tournent autour, c'est pourquoi le standard interdit expressément de le faire (au moins quand le compilateur peut vous dire que vous le faites). Mais nous sommes autorisés à avoir références pour eux; ceux-ci sont implicitement créé.
en raison du point 2, l'utilisation de pointeurs plutôt que de références exigerait que chaque opération de copie utilise l'adresse de l'opérateur ( & ). Oh, attendez, le comité C++ bêtement admis que, pour être surchargé. Ainsi, toute opération de copie devrait réellement utiliser
std::addressof
, C++11 pour obtenir l'adresse. Ainsi, chaque copie aurait besoin de ressembler àType t{std::addressof(v)};
Ou vous pouvez simplement utiliser références.
c'est juste de la nomenclature. Vous pouvez utiliser un pointeur, mais qui avait appelé un constructeur de conversion.
si vous y pensez, cela a du sens, parce que vous copiez un objet à un autre (ergo la "copie"). Pas à partir d'un pointeur à un objet. Si c'était un pointeur, il ne ferait pas de copie, parce que vous ne copiez pas le pointeur sur l'objet, mais plutôt l'objet vers lequel le pointeur pointe.
Pourquoi devrait-il être un pointeur? Un pointeur nul n'aurait pas de sens. Et l'utilisation d'un pointeur ne permettrait pas de copier le temps, donc vous ne pouvais pas faire des choses comme:
MyClass
func()
{
// ...
return MyClass(...);
}
Vous permet de définir un constructeur prenant un pointeur. Mais il ne sera pas être un constructeur de copie, parce qu'il ne pouvait pas être utilisé dans des cas comme le ci-dessus. Et cela n'empêchera pas le compilateur de générer un constructeur de copie.
parce que cela est nié par la norme.
citant le projet de norme c++ n3376-section 12.8.2:
Un constructeur non-template pour la classe X est un constructeur de copie si son premier paramètre est de type x&, const X&, volatile X& ou const volatile X&, et soit il n'y a pas d'autres paramètres, sinon tous les autres paramètres ont des arguments par défaut
Parce qu'un pointeur peut être un nullptr
ce qui devrait être vérifié et les temporairesne peuvent pas avoir de pointeurs vers eux.
en passant par les références, on s'assure qu'un objet réel est passé au constructeur de la copie, alors qu'un pointeur peut avoir une valeur nulle, et faire échouer le constructeur