placement new est une forme particulière de l'opérateur new en C++. Il permet de placer un objet à une adresse donnée dans une zone de mémoire déjà allouée. Il est généralement utilisé pour la gestion manuelle de la mémoire, sous-tend le fonctionnement des allocateurs, du pooling d'objets et de la sérialisation dans des tampons fixes.
Syntaxe :
#include <new> void* memory = malloc(sizeof(MyClass)); MyClass* obj = new (memory) MyClass(args...); // appelle le constructeur à l'adresse memory
Ici, la mémoire est allouée séparément (par exemple, via malloc ou un allocateur), puis le constructeur de la classe est appelé dans cette mémoire. N'oubliez pas d'appeler explicitement le destructeur :
obj->~MyClass(); free(memory);
Avantages :
Un même bloc de mémoire peut-il être utilisé pour placer plusieurs objets consécutivement avec 'placement new', et quelles en sont les conséquences ?
Une réponse incorrecte courante — il est possible de placer de nouveaux objets en mémoire sans se soucier de l'état précédent. En réalité, si un nouvel objet est placé dans la même zone de mémoire qu'un ancien sans appeler son destructeur, cela entraîne une perte de ressources, et l'appel du destructeur entraînera ensuite un comportement indéfini.
Exemple :
void* place = malloc(sizeof(A)); A* a = new (place) A(); B* b = new (place) B(); // l'objet A n'est pas détruit ! comportement indéfini !
Histoire
Dans un système à forte charge, un développeur a mis en œuvre un pool d'objets via
malloc+placement new, mais a oublié d'appeler le destructeur lors du retour d'un objet au pool. En conséquence, les ressources (descripteurs système à l'intérieur des objets) n'ont pas été libérées, entraînant des fuites et un "gel" des serveurs.
Histoire
Dans un projet de sérialisation de données binaires, un tampon et
placement newétaient utilisés pour décoder des objets sur place. Cependant, ils ont oublié d'initialiser la mémoire à zéro avant de placer, ce qui a conduit à la lecture de données non initialisées et à des bogues étranges lors de l'utilisation de structures POD.
Histoire
Un des modules a migré vers le placement de tableaux d'objets à l'aide de
placement newà l'intérieur d'un bloc préalablement alloué. Après l'ajout de nouveaux membres à l'intérieur de la classe avec des destructeurs non triviaux, des plantages de programme sont survenus — ils ont oublié qu'il fallait maintenant appeler explicitement le destructeur pour chaque élément lors du nettoyage, ce qui n'était pas nécessaire auparavant.