void f(int i){ int *pi; pi=new int[i]; // allocation de i int //... }On peut de plus initialiser la valeur:
class Point{ int x,y; public: Point(int a,int b){ x=a;y=b; } }; //... Point *ptr = new Point(2,3); int *p = new int (5); int *q = new int ; // pas d'initialisationPour une classe le
new
appellera le constructeur par défaut
dans le cas où il n'y a pas d'initialisation précisée.
L'opérateur global new peut éventuellement être surchargé, bien
qu'en général il soit plus utile de définir un opérateur new
pour les classes ayant besoin d'allocation dynamique.
On peut spécifier une fonction
new
spécifique retournant un pointeur, cette
fonction aura d'autres arguments. Le premier argument transmis à cette
fonction sera toujours le sizeof(T)
si T
est le
type des objets à allouer.
Il peut être utile, de pouvoir placer un objet à une adresse donnée (par exemple en système un adresse spéciale du matériel), ou de pouvoir allouer les objets dans une zone particulière (par exemple une zone de mémoire partagée) :
void * operator new(size_t, void *p){ return p; } void *ad=(void *) 0xFFFF; int *p=new(ad)int; // alloue un int à l'adress FFFF
On peut aussi, si on sait que l'allocation sera restreinte, améliorer les performances en ne faisant jamais de désallocation :
#define BLOC 1024 class Mon_Alloc{ char *libre; // premier emplacement libre char *max; // fin de l'allocation char *agrandir(size_t s); // agrandit l'espace public: void *alloue(size_t t){ char *p=libre; return ((libre+=t)<max)?p : agrandir(t); } // ... }; void *operator new(size_t s, Mon_Alloc m){ return m.alloue(s); };
La plupart du temps, il est préférable de surcharger
l'opérateur new pour une classe.
L'opérateur global ::operator new()
est appelé sauf
dans le cas d'appel pour un objet de classe T
si
un T::operator new()
existe.
On peut ainsi définir un allocateur global et des allocateurs
spécifiques pour les classes.
Il faut cependant noter qu'un tableau d'objets de classe T
,
n'est pas de classe T
, aussi pour un tableau ce sera
toujours l'allocateur globale ::new
qui sera utilisé
class T{ public: void *operator new(size_t t) }; main(){ T (*t)[2]=new T [10] [2]; // appel ::new T *u=new T; // appel T::new }
Bien entendu, le new
par défaut retourne 0
si
l'allocation a échoué (on devrait toujours tester que le
new
a bien retourné une valeur non nulle...):
#include <assert.h> ... A *p=new A[10]; assert(a!=0);On peut aussi fournir un allocateur de ``rechange''. Quand l'allocateur échoue, il appelle une fonction définie par le dernier appel extern void (*set_new_handler(void(*)()))()+). Les exceptions permettent aussi de gérer les échecs de l'allocation.