New et delete avec constructeurs et destructeurs

L’opérateur new dont nous avons déjà parlé fait en réalité deux choses successivement : primo, il réserve la place mémoire nécessaire à l’objet dans le tas ; secundo, il appelle un constructeur. Inversement, delete appelle d’abord le destructeur, puis libère la place mémoire.

Comme une classe peut avoir plusieurs constructeurs, on peut préciser quel constructeur est appelé au moment de l’appel de new. Il suffit pour cela d’écrire la liste des arguments derrière le nom de classe qui suit new. Voici quelques exemples, basés sur les classes définies aux sections précédentes :

exemple *pe1 = new exemple(1, 2);     // appel du constructeur 2exemple *pe2 = new exemple;           // appel du constructeur 1autre *pa = new autre(1);             // appel de autre::autre(1)classexmpl *c1 = new classexmpl;      // constructeur par défautclassexmpl *c2 = new classexmpl(*c1); // constructeur de copie

Lorsqu’aucun paramètre n’est précisé (c’est-à-dire de la façon dont nous avons utilisé new jusqu’à présent), le constructeur par défaut est appelé ; s’il n’existe pas, une erreur de compilation se produit.

Il est possible de créer un tableau avec new, mais dans ce cas c’est le constructeur par défaut qui est obligatoirement appelé ; il n’y a pas de moyen d’en préciser un autre (contrairement aux tableaux statiques qui peuvent être initialisés par un constructeur à argument unique).

Précisons que cette méthode d’initialisation conjuguée avec new est valable aussi pour des types qui ne sont pas des classes, car ils possèdent toujours un constructeur par défaut (d’où l’écriture que nous avons utilisée jusqu’à présent) et un constructeur de copie. On peut donc écrire par exemple :

double *pd = new double(3.1416);long l = 1000, *pl = new long(l);

qui initialise la case mémoire après sa création (si elle a été réellement créée ; si la place manque, rien n’est fait).

Pour ce qui est de l’instruction delete, il n’y a pas le choix : chaque classe ayant un seul destructeur (éventuellement implicite), c’est celui-là qui est appelé avant de supprimer la place mémoire. Précisons toutefois un problème particulier aux tableaux. Si l’on écrit ceci :

exemple *pex = new exemple[10];// ...delete pex // incorrect;

le compilateur, qui n’a aucun moyen de connaître la taille du tableau pointé par pex, n’appellera le destructeur que pour le premier élément, ce qui peut poser problème. Pour lui demander de tout détruire, il faut préciser explicitement avec delete, le nombre d’éléments à supprimer :

exemple *pex = new exemple[10];// ...delete[10] pex;

Dans ce cas, le destructeur est appelé dix fois pour les dix éléments du tableau.

On notera que pour les types simples, dont le destructeur ne fait rien, il n’est pas nécessaire de procéder ainsi. Nos écritures des chapitres précédents étaient donc correctes.

Précédent Précédent Sommaire Sommaire Suivant Suivant