Dans tous les cas, le passage des paramètres en C++ est un passage par valeur, mais comme cette valeur peut être une référence c'est-à-dire une adresse. Il y a donc dans tous les cas copie des paramètres. En C++, une classe peut définir des opérateurs de conversion ou de copie ; dans le cas d'un passage d'un objet, on fera appel à ces opérateurs puisqu'il y a copie de l'objet, et donc la copie n'est pas toujours une simple recopie d'une zone de la mémoire.
Par contre pour une adresse d'objet (et donc pour une référence), on n'utilisera pas les opérateurs de copie de l'objet, mais éventuellement la conversion des pointeurs qui permet la liaison dynamique des fonctions membres virtuelles.
/* liaison dynamique et references */ #include <iostream.h> class A{ public: virtual void fA(){ cout << "A::fA()\n"; } }; class B:public A{ public: virtual void fA(){ cout<<" B::fA()\n"; } }; void fv(A a){a.fA();} void fr(A &a){a.fA();} main(){ B b; cout << "appel fv(b)-->"; fv(b); cout << "appel fr(b)-->"; fr(b); } // resultat: // appel fv(b)--> A::fA() // appel fr(b)--> B::fA()
Dans le cas où un opérateur de copie est défini pour la classe X
( X::X(const X&)
), le passage par référence n'utilisera pas cet
opérateur. De même, un retour de fonction retournant une référence
n'utilisera pas le constructeur de copie.
L'existence de ces ``copies'' différentes suivant que l'on a un objet ou une adresse d'objet peut être importante en ce qui concerne les performances: il ne faut pas oublier que l'opérateur de copie de la classe est utilisé pour chaque passage de paramètre d'un objet de la classe et aussi pour chaque valeur retournée par une fonction. Par contre, la conversion éventuelle d'adresse, qui peut avoir lieu lors d'un passage d'une adresse (et donc d'une référence) ou dans le retour d'une adresse par une fonction, ne coûte quasiment rien (au plus un décalage).