Références vs pointeurs
Différences clés : nullabilité, réaffectation, indirection et sémantique mémoire.
En C++, deux concepts essentiels existent lors de la manipulation des données : les pointeurs et les références. Les deux servent à « faire référence » à une autre variable ; cependant, ils diffèrent par leur fonctionnement, leur comportement mémoire et leur niveau de sécurité. Dans cet article, nous examinerons les pointeurs et les références, leurs différences et leurs cas d’utilisation à travers des exemples.
1. Qu’est-ce qu’un pointeur ?
Un pointeur est une variable spéciale qui contient une adresse mémoire. Les pointeurs permettent d’accéder indirectement à la valeur d’une autre variable.
#include <iostream>
using namespace std;
int main() {
int nombre = 10;
int *ptr = &nombre; // l’adresse de 'nombre' est assignée à ptr
cout << "Valeur de nombre : " << nombre << endl;
cout << "Valeur de ptr (adresse) : " << ptr << endl;
cout << "Valeur pointée par ptr : " << *ptr << endl;
*ptr = 20; // modification de la valeur via le pointeur
cout << "Nouvelle valeur de nombre : " << nombre << endl;
return 0;
}
Ici, *ptr (déréférencement) permet d’accéder à la valeur de la variable pointée.
Comme les pointeurs peuvent manipuler directement les adresses mémoire, ils sont très puissants — mais aussi dangereux s’ils sont mal utilisés.
2. Qu’est-ce qu’une référence ?
Une référence est un « alias » pour une autre variable. Contrairement à un pointeur, elle ne stocke pas d’adresse mais partage directement la même zone mémoire. Une référence doit être liée à une variable dès sa déclaration.
#include <iostream>
using namespace std;
int main() {
int x = 50;
int &ref = x; // ref est une référence à x
cout << "x : " << x << ", ref : " << ref << endl;
ref = 100; // modification de x via la référence
cout << "Nouvelle valeur de x : " << x << endl;
return 0;
}
Dans cet exemple, ref partage exactement la même adresse mémoire que x.
Ainsi, si l’un change, l’autre change également.
3. Différences entre pointeurs et références
Le tableau suivant montre les principales différences :
| Caractéristique | Pointeur | Référence |
|---|---|---|
| Déclaration | int *p = &x; |
int &r = x; |
| Stocke une adresse ? | Oui, il stocke une adresse mémoire | Non, il est directement lié à la variable |
| Peut être NULL ? | Oui, il peut être nullptr |
Non, il doit toujours référencer une variable |
| Peut être réassigné ? | Oui, il peut pointer vers une autre adresse | Non, une fois lié, il ne peut pas être changé |
| Déréférencement | Accès via *p |
Utilisé directement |
| Gestion mémoire | Manuelle (new/delete) | Automatique |
| Performance | Accès indirect | Accès direct (plus rapide) |
4. Vue mémoire
Voyons comment se comportent les pointeurs et les références en mémoire :
int x = 10;
int *ptr = &x;
int &ref = x;
cout << "&x : " << &x << endl;
cout << "ptr : " << ptr << endl;
cout << "&ref : " << &ref << endl;
Exemple de disposition mémoire :
Variable | Adresse | Valeur
x | 0x61ff0c | 10
ptr | 0x61ff08 | 0x61ff0c
ref | 0x61ff0c | 10
Comme on le voit, ref utilise la même adresse mémoire que x,
tandis que ptr possède sa propre adresse et stocke celle de x.
5. Passage de pointeurs et de références aux fonctions
Les pointeurs et les références peuvent être passés en paramètres de fonction pour modifier des variables externes.
Avec un pointeur
void Incrementer(int *p) {
(*p)++;
}
int main() {
int n = 5;
Incrementer(&n);
cout << n; // 6
}
Avec une référence
void Incrementer(int &r) {
r++;
}
int main() {
int n = 5;
Incrementer(n);
cout << n; // 6
}
Les deux approches produisent le même résultat, mais l’utilisation d’une référence est plus simple et plus sûre.
6. Références const
Si vous ne souhaitez pas qu’une fonction modifie la valeur passée par référence,
utilisez le mot-clé const.
void Afficher(const string &texte) {
cout << texte << endl;
}
int main() {
string message = "C++ est génial !";
Afficher(message);
}
Les références const & permettent de passer de grands objets aux fonctions
sans effectuer de copie, tout en empêchant toute modification du contenu.
C’est également plus performant.
7. Combinaison de pointeurs et de références
Parfois, pointeurs et références sont utilisés ensemble. Par exemple, il est possible d’avoir une référence vers un pointeur.
#include <iostream>
using namespace std;
int main() {
int x = 5;
int *p = &x;
int *&refVersPointeur = p; // référence vers un pointeur
*refVersPointeur = 10;
cout << x << endl; // 10
}
Cette structure peut sembler complexe, mais elle est utile pour la mémoire dynamique ou les fonctions qui doivent modifier des pointeurs.
8. Meilleurs cas d’utilisation
- Pointeur → gestion de la mémoire dynamique (
new/delete), tableaux, opérations bas niveau - Référence → paramètres de fonction, surcharge d’opérateurs, partage d’objets
En C++ moderne, il est souvent préférable d’utiliser des références
ou des smart pointers (comme std::unique_ptr)
plutôt que des pointeurs bruts.
9. TL;DR
- Un pointeur stocke une adresse ; une référence est un alias d’une variable.
- Un pointeur peut être
nullptr; une référence ne le peut pas. - Un pointeur peut être réassigné ; une référence est liée une seule fois.
*paccède à la valeur pointée ; les références sont utilisées directement.- Les références
const &transmettent des objets volumineux sans les copier. - Utilisez les pointeurs pour la gestion mémoire ; les références pour un accès plus simple et plus sûr.
- Tous les exemples peuvent être exécutés sous Visual Studio 2022 ou GCC 11+.