Les références en C++
Une référence est un nom que vous pouvez utiliser comme alias pour une autre variable. Elle est similaire à un pointeur, mais avec des différences cruciales.
Les références deviennent particulièrement importantes dans le contexte de la programmation orientée objet et des fonctions.
Contrairement à un pointeur, une référence :
- Doit être initialisée dès sa déclaration
- Ne peut pas être réaffectée à une autre variable
- Est un alias, pas une variable avec sa propre adresse
Création de références
Une référence est déclarée de la même manière qu'une variable normale, sauf qu'une esperluette (&) est ajoutée entre le type de données et le nom de la variable.
Exemple 1 : Déclaration de références
int x {5};
int& r {x}; // r est un alias de x
int &s {x}; // syntaxe alternative (espace avant &)
int& t; // ERREUR : doit être initialisée !Explication :
int& r {x};: r est une référence à un entier, initialisée avec x.- r devient un alias pour x : toute modification de r affecte x, et vice-versa.
- Une référence doit être initialisée immédiatement (contrairement aux pointeurs).
Exemple 2 : Utilisation d'une référence
int x {5};
int& r {x};
r = 10; // modifie x via la référence
cout << x; // affiche 10
cout << r; // affiche aussi 1010 10
Références et pointeurs
Une référence est similaire à un pointeur qui pointe toujours vers la même chose. Cependant :
- Un pointeur est une variable qui pointe vers une autre variable.
- Une référence n'est qu'un alias et n'a pas d'adresse propre.
Exemple 3 : Adresse d'une référence
int x {5};
int& r {x};
int* ptr = &r; // l'adresse assignée à ptr est l'adresse de x
// &r et &x donnent la même adresse !Prendre l'adresse d'une référence donne l'adresse de la variable référencée. La référence elle-même n'a pas d'adresse propre.
Comparaison détaillée
| Caractéristique | Pointeur | Référence |
|---|---|---|
| Initialisation | Peut être déclaré sans initialisation (pointeur nul) | Doit être initialisé immédiatement |
| Réaffectation | Peut pointer vers différentes variables | Ne peut pas être réaffecté (reste lié à la même variable) |
| Valeur nulle | Peut être nullptr | Ne peut pas être nul (doit toujours référencer quelque chose) |
| Déréférencement | Nécessite * pour accéder à la valeur | Utilisation directe (comme une variable normale) |
| Adresse propre | Oui (on peut prendre l'adresse du pointeur) | Non (l'adresse de la référence est celle de la variable) |
Généralement, chaque fois qu'un pointeur n'a pas besoin d'être réaffecté, une référence doit être utilisée à la place, car une référence est plus sûre : elle doit toujours faire référence à quelque chose, donc pas besoin de vérifier si elle est nulle.
Exemple 4 : Piège avec les références
Il est possible qu'une référence soit invalide - par exemple, lorsqu'une référence fait référence à un pointeur nul.
int* ptr = nullptr; // pointeur nul
int& ref = *ptr; // DANGER : ref est une référence à une zone mémoire invalide
ref = 10; // ERREUR : accès mémoire invalideCe type d'erreur est plus facile à éviter avec des références qu'avec des pointeurs, car on ne peut pas déclarer une référence non initialisée. Cependant, il faut rester vigilant avec les déréférencements de pointeurs.
Références Rvalue (C++11 et ultérieur)
Avec C++11 est venu un nouveau type de référence appelé référence rvalue. Cette référence peut lier et modifier des objets temporaires (rvalues), tels que des valeurs littérales et des valeurs de retour de fonction.
Une référence rvalue est formée en plaçant deux esperluettes (&&) après le type.
Exemple 5 : Référence rvalue
int&& ref = 1 + 2; // référence rvalue vers le résultat temporaire de 1+2La référence rvalue prolonge la durée de vie de l'objet temporaire et lui permet d'être utilisé comme une variable ordinaire.
Exemple 6 : Utilisation d'une référence rvalue
int&& ref = 1 + 2;
ref += 3; // modifie le temporaire
cout << ref; // affiche 66
Les références rvalue permettent d'éviter les copies inutiles lorsqu'il s'agit d'objets temporaires. Cela offre de meilleures performances, en particulier lors de la gestion de types plus volumineux, tels que des chaînes et des objets.
Elles sont à la base de la sémantique de déplacement (move semantics) introduite en C++11.
Comparaison des types de références
| Type | Syntaxe | Peut référencer | Usage typique |
|---|---|---|---|
| Référence lvalue | type& | Variables modifiables (lvalues) | Paramètres de fonction, alias |
| Référence const lvalue | const type& | Variables et temporaires (lecture seule) | Paramètres pour éviter les copies |
| Référence rvalue | type&& | Temporaires (rvalues) | Sémantique de déplacement, perfect forwarding |
Manipulation de références
Considérez le code suivant :
int a = 10;
int b = 20;
int& ref = a;
ref = b; // Que se passe-t-il ici ?
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "ref = " << ref << endl;Questions :
- Quelles sont les valeurs affichées ?
- Que signifie l'instruction
ref = b;? - La référence ref est-elle maintenant un alias pour b ?
- Modifiez le code pour échanger les valeurs de a et b en utilisant une référence.
- Valeurs affichées :
a = 20 b = 20 ref = 20
- Signification de
ref = b;:Cette instruction n'est pas une réaffectation de la référence ! Une référence ne peut pas être réaffectée à une autre variable.
ref = b;signifie : "assigner la valeur de b à la variable référencée par ref". Comme ref est un alias de a, cela équivaut àa = b;. - La référence ref est-elle maintenant un alias pour b ?
Non. ref reste un alias pour a. Une référence ne peut pas être réaffectée. Elle conserve le même lien pour toute sa durée de vie.
- Échange des valeurs avec une référence :
Pour échanger a et b, on ne peut pas utiliser directement une référence. Voici une fonction qui échange deux entiers en utilisant des références :
void echanger(int& x, int& y) { int temp = x; x = y; y = temp; } int a = 10, b = 20; echanger(a, b); // a = 20, b = 10
- Une référence est un alias pour une variable existante (déclarée avec
&). - Une référence doit être initialisée dès sa déclaration.
- Une référence ne peut pas être réaffectée à une autre variable.
- Une référence n'a pas d'adresse propre (son adresse est celle de la variable référencée).
- Les références sont plus sûres que les pointeurs car elles ne peuvent pas être nulles (mais attention aux références invalides).
- Les références rvalue (
&&) permettent de lier des temporaires et sont à la base de la sémantique de déplacement. - Les références sont très utilisées comme paramètres de fonctions pour éviter les copies et permettre les modifications.
- Règle générale : préférer une référence à un pointeur quand la réaffectation n'est pas nécessaire.
Discussion (0)
Soyez le premier à laisser un commentaire !
Laisser un commentaire
Votre commentaire sera visible après modération.