Chargement...

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éristiquePointeurRé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

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.
  • *p accè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+.

Articles connexes