Références vs Pointeurs en C++ : Comprendre la différence

Références vs Pointeurs en C++ : Comprendre la différence

Amine Abidi - Lead Software Engineer C++/Qt - Associé PointerLab

Publié par Amine Abidi - Lead Software Engineer C++/Qt - Associé PointerLab

Introduction

En C++, les références (&) et les pointeurs (*) sont des outils essentiels pour manipuler la mémoire et les données efficacement. Bien qu'ils soient liés à la gestion des adresses mémoire, ils ont des rôles et des comportements différents. Dans cet article, nous allons explorer ces différences et les situations où utiliser l'un ou l'autre.


1. Références en C++

Une référence agit comme un alias pour une variable existante. Elle ne peut pas être réassignée pour référencer une autre variable après sa déclaration.

Caractéristiques des références :

  • Utilisent le symbole & dans leur déclaration.
  • Doivent être initialisées au moment de leur déclaration.
  • Ne peuvent pas être nulles.

Exemple simple :

#include <iostream>
using namespace std;
 
int main() {
    int a = 10;
    int &ref = a;  // ref est une référence à a
 
    ref += 5;  // Modifie directement la valeur de a
    cout << "Valeur de a : " << a << endl;  // Affiche 15
 
    return 0;
}

2. Pointeurs en C++

Un pointeur est une variable qui stocke l'adresse mémoire d'une autre variable. Contrairement à une référence, un pointeur peut être réassigné ou nul.

Caractéristiques des pointeurs :

  • Utilisent le symbole * pour leur déclaration.
  • Peuvent être initialisés ou laissés à nullptr.
  • Peuvent être réassignés pour pointer vers une autre adresse.

Exemple simple :

#include <iostream>
using namespace std;
 
int main() {
    int a = 10;
    int *ptr = &a;  // ptr pointe vers a
 
    *ptr += 5;  // Modifie directement la valeur de a via ptr
    cout << "Valeur de a : " << a << endl;  // Affiche 15
 
    return 0;
}
 

3. Différences principales

Aspect Référence Pointeur
Syntaxe Utilise & dans la déclaration. Utilise * pour la déclaration.
Initialisation Obligatoire à la déclaration. Peut être non initialisé (nullptr).
Reassignation Impossible après initialisation. Peut pointer vers différentes adresses.
Nullabilité Ne peut pas être nulle. Peut être nullptr.
Utilisation Alias pour une variable existante. Stocke une adresse mémoire.

4. Cas pratiques : Passage par référence vs passage par pointeur

Avec une référence :

void incrementer(int &ref) {
    ref += 1;  // Modifie directement la variable d'origine
}
 
int main() {
    int a = 10;
    incrementer(a);
    cout << "Valeur de a : " << a << endl;  // Affiche 11
    return 0;
}
 

5. Quand utiliser l'un ou l'autre ?

Utilisez une référence :

  • Si la variable ne doit pas être réassignée.
  • Si vous voulez simplifier la syntaxe (pas besoin de * pour accéder aux valeurs).
  • Pour les paramètres de fonction quand l'objet ne doit pas être nullptr.

Utilisez un pointeur :

  • Si vous devez manipuler des adresses directement.
  • Si la variable doit pouvoir être réassignée à une autre adresse.
  • Si la valeur peut être absente (nullptr).

6. Exercice pratique

Énoncé :

  1. Implémentez une fonction qui inverse deux entiers en utilisant une référence.
  2. Implémentez une autre version qui utilise un pointeur.
  3. Testez les deux fonctions dans un programme.

Solution proposée :

Avec une référence :
#include <iostream>
using namespace std;
 
void echanger(int &a, int &b) {
    int temp = a;
    a = b;
    b = temp;
}
 
int main() {
    int x = 10, y = 20;
    cout << "Avant inversion : x = " << x << ", y = " << y << endl;
 
    echanger(x, y);
 
    cout << "Après inversion : x = " << x << ", y = " << y << endl;
    return 0;
}
 

Avec un pointeur :

#include using namespace std;

void echanger(int *a, int *b) { if (a && b) { // Vérifie si les pointeurs ne sont pas nuls int temp = *a; *a = *b; *b = temp; } }

int main() { int x = 10, y = 20; cout << "Avant inversion : x = " << x << ", y = " << y << endl;

echanger(&x, &y);

cout << "Après inversion : x = " << x << ", y = " << y << endl;
return 0;

}


Conclusion

Les références et les pointeurs sont deux outils puissants du langage C++ qui permettent de manipuler efficacement la mémoire. Comprendre leurs différences et savoir quand les utiliser est essentiel pour écrire du code robuste et performant.

  • Les références : Elles sont utilisées lorsque vous souhaitez garantir que l'argument d'une fonction ou une variable se réfère toujours à une autre. Elles ne peuvent pas être nulles et sont souvent préférées pour des raisons de sécurité et de lisibilité lorsque vous travaillez avec des données qui ne doivent pas être modifiées ou qui doivent être passées facilement sans copie.

  • Les pointeurs : Ils sont plus flexibles et permettent de manipuler directement des adresses mémoire. Ils peuvent être utilisés pour gérer des tableaux, manipuler de manière dynamique la mémoire ou modifier des objets à l'extérieur de la portée d'une fonction. Cependant, ils peuvent introduire des risques de gestion de mémoire et doivent être utilisés avec précaution pour éviter des erreurs comme les fuites de mémoire ou les accès à des adresses invalides.

Dans le prochain article, nous explorerons la gestion dynamique de la mémoire avec les opérateurs new et delete, ainsi que les smart pointers (std::unique_ptr, std::shared_ptr) pour simplifier la gestion de la mémoire.


À propos de pointerlab

pointerlab s’inspire des fonctions lambda en C++, symbole de code concis, flexible et performant. C’est cette philosophie, mêlant rigueur et modernité, que nous mettons au service des défis de nos clients.

Experts C++ et Qt, nous maîtrisons des technologies de pointe comme Qt, OpenGL, OpenCV et Unreal Engine 5 pour concevoir des solutions logicielles sur mesure et robustes. Présents dans des secteurs exigeants tels que la simulation 3D, le médical ou l’aéronautique, nous allions innovation et expertise pour relever les défis les plus complexes.

Rejoignez la communauté C++ France sur Discord !

Développez votre réseau et boostez votre carrière avec la communauté C++ France