next up previous contents index
suivant: L'organisation d'un processus monter: main précédent: Pointeurs et tableaux   Table des matières   Index


Allocation dynamique

Ce mode d'allocation, aussi appelé allocation sur le tas (Cf. § 73), est présent dans de nombreux langages à l'exception notable de Fortran 77. Un objet alloué dynamiquement ne résulte pas de la définition du nom qui le désigne, à la différence des objets statiques et automatiques, mais résulte d'un appel à l'un des opérateurs new et new[]. L'opérateur new appliqué à un type $T$, alloue un bloc de mémoire de ce type dans le tas, et retourne l'adresse de ce bloc, de type $T$*, qui est différente de NULL si l'allocation réussit. L'opérateur de dés-allocation correspondant est delete.


\begin{figurette}
% latex2html id marker 4807\begin{center}
\leavevmode
\fb...
...tialisation d'un pointeur par allocation dynamique} \end{center} \end{figurette}

C'est une des façons d'initialiser un pointeur :


int *ip = new int;
// ...
delete ip;

Un second opérateur d'allocation dynamique, new[] permet la création de tableaux dynamiques. L'opérateur new[] appliqué à un type $T$, et à une expression arithmétique entière, de valeur $n\ge
0$ alloue un bloc de mémoire de ce type dans le tas, capable de contenir $n$ objets consécutifs et retourne l'adresse de ce bloc, de type $T$*, qui est différente de NULL si l'allocation réussit. Ces $n$ objets peuvent être désignés à l'aide de la même syntaxe que les éléments d'un tableau. L'opérateur de dés-allocation correspondant à new[] est delete[].

Par exemple, on peut maintenant définir un tableau dynamique de double dont la taille, puis les éléments, sont lus sur l'entrée standard en cours d'exécution, :


int f() {
  double *t;
  int n, i;

  cin >> n;
  t = new double[n];
  for (i=0; i<n; i++) {
    cin >> t[i];
  }
  ...
  delete[] t;
  return ...;
}

Il faut noter que la variable t, comme toute variable locale, est allouée automatiquement, dans la pile ; la valeur qui lui est affectée est l'adresse d'un objet alloué dynamiquement, dans le tas. Soulignons aussi que t n'est pas de type tableau, les tableaux étant soit globaux et alloués statiquement, soit locaux et alloués automatiquement sur la pile. Bien que t ne soit pas un tableau, la notation t[$i$] est utilisable pour accéder à ses éléments alloués consécutivement.

Ces tableaux dynamiques sont également utilisés pour permettre à une fonction de << retourner un tableau >>, ce qui, rappelons-le, est impossible (le type de retour d'une fonction ne peut être qu'un type simple, un type pointeur ou un struct). Pour contourner cette difficulté, il ne faut surtout pas commettre l'erreur de retourner l'adresse d'un tableau défini localement dans la fonction :


double *vecteur_add_ERREUR(int n, double x[], double y[]) {
  double z[n];
  int i;

  for(i=0; i<n; i++) {
    z[i] = x[i] + y[i];
  }
  return z;                 // ERREUR : adresse locale retournée
}

En effet, l'allocation du tableau z étant automatique, le bloc alloué est aussi dés-alloué à la sortie de la fonction, donc la valeur retournée est l'adresse d'un bloc mémoire qui n'est plus alloué. Le résultat est alors imprévisible.

Signalons l'erreur voisine qui consiste à retourner une variable locale par référence :


complexe& complexe_add_ERREUR(const complexe& x, const complexe& y) {
  complexe z;

  z.re = x.re + y.re;
  z.im = x.im + y.im;

  return z;                 // ERREUR : objet local retourné
}

On doit plutôt, soit utiliser un tableau défini avant l'appel et le passer en argument, soit recourir à l'allocation dynamique à l'intérieur de la fonction pour allouer un bloc de mémoire où le résultat sera écrit ; la fonction retourne dans ce cas l'adresse du bloc alloué. On procède ainsi :


double *vecteur_add(int n, const double x[], const double y[]) {
  int i;
  double *z = new double[n];

  for(i=0; i<3; i++) {
    z[i] = x[i] + y[i];
  }
  return z;
}

et on l'appelle ainsi :


  double x[] = {1.0, 2.0, 3.0};
  double y[] = {4.0, 5.0, 6.0};
  double *z = vecteur_add(3, x, y);
  // ...
  delete[] z;


next up previous contents index
suivant: L'organisation d'un processus monter: main précédent: Pointeurs et tableaux   Table des matières   Index
R Lalement