placement new — это особая форма оператора new в C++. Она позволяет размещать объект по заданному адресу в уже выделенной области памяти. Обычно используется для ручного управления памятью, лежит в основе работы аллокаторов, пулинга объектов и сериализации в фиксированные буферы.
Синтаксис:
#include <new> void* memory = malloc(sizeof(MyClass)); MyClass* obj = new (memory) MyClass(args...); // вызывает конструктор по адресу memory
Здесь память выделяется отдельно (например, через malloc или аллокатор), а затем конструктор класса вызывается в этой памяти. Не забудьте явно вызвать деструктор:
obj->~MyClass(); free(memory);
Плюсы:
Может ли один и тот же блок памяти использоваться для размещения нескольких объектов подряд с помощью 'placement new', и к каким последствиям это приводит?
Частый неверный ответ — можно размещать новые объекты в памяти, не заботясь о предыдущем состоянии. На самом деле, если в той же области памяти размещать новый объект поверх старого без вызова его деструктора, произойдет утечка ресурсов, и вызов деструктора потом приведёт к UB.
Пример:
void* place = malloc(sizeof(A)); A* a = new (place) A(); B* b = new (place) B(); // объект A не разрушен! UB!
История
В высоконагруженной системе разработчик реализовал пул объектов через
malloc+placement new, но забыл вызывать деструктор при возврате объекта в пул. В итоге ресурсы (системные дескрипторы внутри объектов) не освобождались, приводя к утечкам и "зависанию" серверов.
История
В проекте для сериализации бинарных данных использовался буфер и
placement new, чтобы декодировать объекты на месте. Однако забыли инициализировать память нулями перед размещением, что привело к чтению неинициализированных данных и странным багам при работе с POD-структурами.
История
Один из модулей мигрировал на размещение массивов объектов с помощью
placement newвнутри заранее выделенного блока. После добавления внутри класса новых членов с нетривиальными деструкторами возникли аварийные завершения программы — забыли, что теперь нужно явно вызывать деструктор для каждого элемента при очистке, чего раньше не требовалось.