Ответ
Placement new — это особая форма оператора new, которая не выделяет память, а конструирует объект по заранее предоставленному адресу. Это низкоуровневая операция, используемая для разделения этапов выделения памяти и инициализации объекта.
Основные отличия от обычного new:
- Не выделяет память: Вы сами управляете областью памяти (стек, выделенный ранее буфер, shared memory).
- Не выбрасывает
std::bad_alloc: Поскольку память уже есть, исключение на этапе размещения не генерируется (но конструктор объекта может выбросить своё исключение). - Требует ручного вызова деструктора: Память не освобождается оператором
delete, деструктор нужно вызывать явно.
Синтаксис: new (адрес_памяти) Тип(аргументы_конструктора)
Пример использования:
#include <new> // Необходим для placement new
#include <iostream>
class MyClass {
public:
int value;
MyClass(int v) : value(v) {
std::cout << "Constructor called. Value: " << value << 'n';
}
~MyClass() {
std::cout << "Destructor called.n";
}
};
int main() {
// 1. Выделяем память (например, в стеке или из пула)
alignas(MyClass) char buffer[sizeof(MyClass)];
// 2. Конструируем объект в выделенной памяти с помощью placement new
MyClass* obj = new (buffer) MyClass(42);
std::cout << "Object value: " << obj->value << 'n'; // 42
// 3. Явно вызываем деструктор (обязательный шаг!)
obj->~MyClass();
// Память `buffer` будет освобождена при выходе из области видимости.
return 0;
}
Типичные сценарии применения:
- Оптимизация производительности: Создание объектов в заранее выделенном пуле памяти (memory pool) для избежания фрагментации кучи и ускорения аллокаций.
- Низкоуровневое программирование: Работа с разделяемой памятью (shared memory), аппаратными регистрами или памятью, выделенной средствами C (
malloc). - Контейнеры: Реализация стандартных контейнеров (например,
std::vector), которые выделяют сырую память блоками и затем конструируют в ней объекты.
Важное предупреждение: Необходимо следить за выравниванием (alignment) предоставляемой памяти. Использование alignas или специализированных аллокаторов помогает избежать ошибок выравнивания (misalignment), ведущих к падению производительности или краху программы на некоторых архитектурах.