Compilation & Directives de préprocesseur Pointeurs, Références & Allocation Dynamique de Mémoire Spécificités du C++ (indépendantes de la POO) Structures & Classes Encapsulation des données Constructeur & Destructeur de classe Copie d'objets Amitié & Surcharge d'opérateur Héritage (Partie 1) Héritage (Partie 2) Patrons de fonctions et de classes Introduction à la librairie standard
Retour menu principal

Pointeurs, Références & Allocation Dynamique de Mémoire


Rappels sur les adresses et pointeurs

  • Tout objet manipulé par l’ordinateur est stocké en mémoire. Selon la nature de l’objet, l’espace en mémoire alloué varie : par exemple, entier = 32 ou 64 bits
  • L'adresse est l’endroit où se trouve la variable en mémoire. Elle s’obtient via la syntaxe suivante : &NomDeLaVariable
  • L’adresse n’étant ni plus ni moins qu’une valeur, on peut donc stocker cette valeur dans une variable : un pointeur est ainsi un conteneur d’adresse
  • Déclaration d’un pointeur :

    int i = 10;
    int * pt_i = &i;
    int j = *pt_i;
    

Notion de référence en C++

Le C++ introduit la notion de référence afin de faciliter la manipulation des variables

Pointeur

// Pointeur
int i = 10;
int * pt_i = &i;
(*pt_i)++;

Référence

// Référence
int i = 10;
int & ref_i = i;
ref_i++;

:BEAMER_ENV: ignoreheading

  • La déclaration d’une référence ne crée pas de nouvel objet
  • Toute référence doit se référer à un identificateur : int & ref_i; ne compilera pas. Il est nécessaire d'initialiser une référence.
  • Une référence pointe toujours vers le même objet, on ne peut pas changer sa destination.

Références en tant qu’arguments de fonctions

Transmission par adresse

void echange(int * a, int * b)
{
  int c = *a;
  *a = *b;
  *b = c;
}
...
int x = 10;
int y = 20;
echange(&x, &y);

Transmission par référence

void echange(int & a, int & b)
{
  int c = a;
  a = b;
  b = c;
}
...
int x = 10;
int y = 20;
echange(x, y);

Allocation dynamique de mémoire

L’allocation dynamique de mémoire est nécessaire dès lors que la taille d’un objet (ou sa nature) n’est connue que lors de l’exécution du programme. La déclaration

unsigned int n = 0;
std::cin >> n;
double tableau[n];

est rejetée du fait que le compilateur ne connait pas, au préalable, l’espace mémoire nécessaire à l’allocation (statique).

Utilisation des opérateurs new et delete

  • Pour rappel, en langage C, la gestion dynamique de mémoire fait appel aux fonctions malloc et free (librairie stdlib.h)
  • C++ propose deux nouveaux opérateurs :
    • new alloue une certaine quantité de mémoire et renvoie un pointeur sur le début du tableau :

      unsigned int n = 0;
      std::cin >> n;
      double * tableau = new double[n];
      
    • delete[] libère l’espace mémoire :

      delete[] tableau;
      

Portée & Durée de vie des variables

Durée de vie limitée au bloc (ici boucle for)

for (int i = 0; i < 10; i++) {
  int k = 0;
  // À la fin du bloc,
  // destruction de k
 }

Durée de vie indépendante du bloc

for (int i = 0; i < 10; i++) {
  int * k = new int(0);
  // À la fin du bloc,
  // k existe en mémoire
 }

Fuite de mémoire garantie

Portée & Durée de vie des variables

Durée de vie limitée au bloc (ici boucle for)

for (int i = 0; i < 10; i++) {
  int k = 0;
  // À la fin du bloc,
  // destruction de k
 }

Durée de vie indépendante du bloc

for (int i = 0; i < 10; i++) {
  int * k = new int(0);
  ...
  delete k;
}

Portée & Durée de vie des variables

Allocation sur la pile (“stack”)

int * pointeur_dix()
{
  int a = 10;
  return &a;
}

int main()
{
  int * pb = pointeur_dix();
  cout << *pb << endl;

  return 0;
}

Allocation sur le tas (“heap”)

Portée & Durée de vie des variables

Allocation sur la pile (“stack”)

int * pointeur_dix()
{
  int a = 10;
  return &a;
}

int main()
{
  int * pb = pointeur_dix();
  cout << *pb << endl;

  return 0;
}

Le pointeur retourné contient une adresse obsolète

Allocation sur le tas (“heap”)

int * pointeur_dix()
{
  int * pa = new int(10);
  return pa;
}

int main()
{
  int * pb = pointeur_dix();
  cout << *pb << endl;
  delete pb;
  return 0;
}