C++, comme Pascal, offre deux modes de passage des arguments à une fonction : par valeur, et par référence. Par contre, C12, Java et CAML, par simplicité n'en offrent qu'un, le passage par valeur, tandis que Fortran fait le choix inverse.
Dans un passage par référence, ce n'est pas la valeur de
l'argument qui est utilisée dans le corps de la fonction, c'est
l'argument lui-même, en tant qu'objet, qui est utilisé et modifié : ces
modifications resteront donc visibles après le retour de la fonction.
Le passage par référence s'applique à un argument si le paramètre
correspondant a été déclaré en acollant &
à son type. L'argument
correspondant doit être une expression désignant un objet.
Par exemple, voici une procédure qui incrémente son argument entier13 :
void inc(int& x) { x = x+1; } int main() { int n = 4; inc(n); cout << n << endl; // n vaut maintenant 5 return 0; }
Un autre exemple classique est la fonction qui échange la valeur de deux variables :
void swap(int& x, int& y) { int temp = x; x = y; y = temp; } int main() { int a=1, b=2; swap(a, b); cout << a << " " << b << endl; return 0; }
Ce mécanisme est basé sur le constructeur de types références &
:
si est un type, &
est le type des références aux objets de
type . Celui-ci peut figurer comme type d'argument et comme type de
retour des fonctions. Ce sera le mode de passage privilégié quand les
arguments sont des objets volumineux. Le passage d'argument et le
retour sont basées sur l'initialisation des variables de ce type. On
doit initialiser une variable de type &
par une variable (ou
plus généralement une expression qui désigne un objet) de type .
Il serait incorrect d'appeler inc(4) ou swap(1,2), car
les arguments de ces appels sont des valeurs et ne désignent aucun objet
(c'est-à-dire n'ont pas d'existence en mémoire). Il serait également
incorrect d'appeler inc(n) si n est définie comme une
constante :
const int n = 4; inc(n); // ERREUR inc(4); // ERREUR
Dans les deux cas, il s'agit d'une erreur de type. La fonction
inc a un paramètre de type int&
. Or les règles de typage
du langage interdisent que l'on initialise une variable de type
&
par une variable de type const (car la
constance serait perdue) ou par une valeur de type (car une
valeur n'est pas un objet).