placement new is een speciale vorm van de new operator in C++. Het stelt je in staat om een object op een specifieke locatie in al toegewezen geheugen te plaatsen. Het wordt meestal gebruikt voor handmatig geheugenbeheer, vormt de basis voor allocators, object pooling en serialisatie naar vaste bufffers.
Syntax:
#include <new> void* memory = malloc(sizeof(MyClass)); MyClass* obj = new (memory) MyClass(args...); // roept de constructor aan op het adres memory
Hier wordt het geheugen apart toegewezen (bijvoorbeeld via malloc of een allocator), en vervolgens wordt de constructor van de klasse op dat geheugen aangeroepen. Vergeet niet om de destructor expliciet aan te roepen:
obj->~MyClass(); free(memory);
Voordelen:
Kan hetzelfde geheugenblok worden gebruikt om meerdere objecten achtereenvolgens te plaatsen met 'placement new', en welke gevolgen heeft dit?
Een veelvoorkomend verkeerd antwoord is dat je nieuwe objecten in het geheugen kunt plaatsen zonder je zorgen te maken over de vorige staat. In werkelijkheid, als je een nieuw object bovenop een oud object in hetzelfde geheugen plaatst zonder de destructor aan te roepen, leidt dit tot resource-lekken, en het aanroepen van de destructor leidt dan tot UB.
Voorbeeld:
void* place = malloc(sizeof(A)); A* a = new (place) A(); B* b = new (place) B(); // object A is niet vernietigd! UB!
Verhaal
In een hoogbelaste systeem heeft de ontwikkelaar een objectpool geïmplementeerd via
malloc+placement new, maar vergat de destructor aan te roepen bij het retourneren van een object naar de pool. Uiteindelijk werden de resources (systeem descriptors binnen objecten) niet vrijgegeven, wat leidde tot lekken en 'bevriezing' van servers.
Verhaal
In een project voor het serialiseren van binaire data werd een buffer en
placement newgebruikt om objecten ter plaatse te decoderen. Echter werd vergeten om het geheugen op nul te initialiseren voordat het werd geplaatst, wat leidde tot het lezen van niet-geïnitieerde gegevens en vreemde bugs bij het werken met POD-structuren.
Verhaal
Een van de modules migreerde naar het plaatsen van arrays van objecten met behulp van
placement newbinnen een vooraf toegewezen blok. Na het toevoegen van nieuwe leden met niet-triviale destructors binnen de klasse, ontstonden er programma-crashes — vergeten dat de destructor nu expliciet voor elk element moet worden aangeroepen bij het opruimen, wat eerder niet nodig was.