next up previous contents
Next: delete Up: Allocation Previous: Allocation

new

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'initialisation
Pour 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.




Mon Oct 20 14:02:48 MET 1997