Chargement...

Passer des paramètres par pointeurs

Transmettre des adresses aux fonctions : modification des valeurs et coûts associés.

En C++, les paramètres des fonctions sont généralement transmis par valeur (by value) ou par référence (by reference). Cependant, il arrive parfois qu'une fonction doive travailler directement avec une adresse mémoire — dans ce cas, on utilise la méthode de passage de paramètres par pointeur. Cette approche permet de modifier les variables directement en mémoire, sans les copier.


1. Différence entre passage par valeur et par pointeur

Lorsqu’un paramètre est passé par valeur, une copie de la variable originale est créée. Les modifications effectuées à l’intérieur de la fonction n’affectent pas la variable d’origine. Lorsqu’il est passé par pointeur, la fonction accède directement à la mémoire originale.


#include <iostream>
using namespace std;

void ChangerParValeur(int x) {
    x = 20;
}

void ChangerParPointeur(int *p) {
    *p = 20;
}

int main() {
    int nombre = 10;

    ChangerParValeur(nombre);
    cout << "Après passage par valeur : " << nombre << endl; // 10

    ChangerParPointeur(&nombre);
    cout << "Après passage par pointeur : " << nombre << endl; // 20
}

Conclusion : Le passage de paramètres par pointeur permet de modifier la valeur d'une variable directement via son adresse mémoire.


2. Déclaration des paramètres pointeurs

Lorsqu’une fonction utilise un paramètre pointeur, le type du paramètre est indiqué avec *. Lors de l’appel de la fonction, l’adresse de la variable est transmise à l’aide de &.


void Modifier(int *ptr) {
    *ptr = *ptr + 5;
}

À l’intérieur de la fonction, l’expression *ptr modifie la valeur réelle de la variable pointée. Cette méthode permet d’économiser de la mémoire et d’améliorer les performances.


3. Plusieurs paramètres pointeurs

Plusieurs adresses peuvent être transmises à une fonction en même temps. Cette technique est utile pour les opérations arithmétiques ou pour échanger des valeurs (swap).


#include <iostream>
using namespace std;

void EchangerValeurs(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int x = 5, y = 10;
    EchangerValeurs(&x, &y);
    cout << "x: " << x << ", y: " << y << endl; // x:10, y:5
}

Dans cet exemple, les paramètres pointeurs permettent d’accéder directement aux adresses mémoire des variables. Les valeurs des variables en dehors de la fonction ont été modifiées avec succès.


4. Paramètres pointeurs const

Si une fonction ne doit pas modifier la valeur transmise, le paramètre pointeur peut être déclaré avec const.


void Afficher(const int *p) {
    cout << "Valeur : " << *p << endl;
}

int main() {
    int nombre = 42;
    Afficher(&nombre);
}

Dans ce cas, la fonction ne peut que lire la donnée, sans la modifier. Cela améliore la sécurité du code et évite les manipulations accidentelles.


5. Pointeurs et tableaux (paramètres de tableau)

En C++, les tableaux se comportent comme des pointeurs. Lorsqu’un tableau est passé à une fonction, l’adresse de son premier élément est transmise.


void AfficherTableau(int *tab, int taille) {
    for (int i = 0; i < taille; i++) {
        cout << tab[i] << " ";
    }
    cout << endl;
}

int main() {
    int nombres[] = {10, 20, 30, 40, 50};
    AfficherTableau(nombres, 5);
}

À l’intérieur de la fonction, on peut accéder aux éléments avec tab[i] ou *(tab + i). Le nom du tableau représente en réalité l’adresse de son premier élément.


6. Paramètres pointeurs et mémoire dynamique

Les paramètres pointeurs peuvent également être utilisés avec des données créées dynamiquement dans le tas (heap).


#include <iostream>
using namespace std;

void Remplir(int *p, int taille) {
    for (int i = 0; i < taille; i++)
        p[i] = (i + 1) * 10;
}

int main() {
    int *tableau = new int[5]; // Tableau dynamique dans le tas
    Remplir(tableau, 5);

    for (int i = 0; i < 5; i++)
        cout << tableau[i] << " ";

    delete[] tableau; // Libérer la mémoire
}

Dans cet exemple, le paramètre pointeur a été utilisé pour remplir un tableau alloué dans le tas. Après l’appel de la fonction, la mémoire doit être libérée avec delete[].


7. Pointeur vers pointeur (double pointeur)

On peut également stocker l’adresse d’un pointeur. Dans ce cas, on parle de pointeur vers pointeur. Cela est particulièrement utile lorsqu’une fonction doit modifier le pointeur lui-même.


void ModifierPointeur(int **p) {
    static int valeur = 99;
    *p = &valeur; // change l’adresse pointée par le pointeur
}

int main() {
    int x = 10;
    int *ptr = &x;

    ModifierPointeur(&ptr);
    cout << "Nouvelle valeur : " << *ptr << endl; // 99
}

Cette méthode permet à la fonction de modifier non seulement la donnée, mais aussi le pointeur lui-même. Elle est souvent utilisée dans les fonctions qui gèrent la mémoire dynamique.


8. Alternative moderne en C++ : Références et Smart Pointers

Avec le C++ moderne (C++11 et ultérieur), les paramètres pointeurs classiques sont souvent remplacés par des références ou des pointeurs intelligents (smart pointers) :

Cependant, dans la programmation système, les systèmes embarqués ou les applications critiques en performance, les paramètres pointeurs classiques sont encore largement utilisés.


9. TL;DR

  • int *p → définit un paramètre pointeur ; la fonction est appelée avec &var.
  • Les paramètres pointeurs permettent d’accéder directement à la mémoire.
  • const int *p → lecture seule.
  • Les tableaux se comportent comme des pointeurs et sont transmis par adresse.
  • int **p → double pointeur ; la fonction peut modifier le pointeur lui-même.
  • En C++ moderne, les références et les smart pointers sont plus sûrs.
  • Tous les exemples peuvent être exécutés avec Visual Studio 2022 ou GCC 11+.

Articles connexes