placement new – это специальная форма оператора new, которая размещает объект в уже выделенной памяти вместо того, чтобы выделять её заново. placement new НЕ выделяет память (мы сами передаём адрес).
Просто вызывает конструктор в указанном месте.
void* ptr = malloc(sizeof(int)); // Выделяем память вручную
int* num = new(ptr) int(42); // Размещаем объект в этой памяти
Синтаксис
placement newnew (адрес) Type(аргументы конструктора);
адрес – указатель на уже выделенную память. Type(аргументы конструктора) – объект создаётся в этом месте. #include <iostream>
int main() {
char buffer[sizeof(int)]; // Буфер памяти (размер как у int)
int* p = new (buffer) int(123); // Размещаем int в этом буфере
std::cout << "Значение: " << *p << std::endl; // 123
}
🚩Когда используется `placement new`?
🟠Оптимизация выделения памяти
Например, если у нас часто создаются и удаляются объекты, но память уже есть. Не нужно каждый раз вызывать
new и delete. 🟠Размещение объектов в особых областях памяти
Например, на стеке (
char buffer[100]), в shared memory, или в выделенной заранее области (malloc). 🟠Создание объекта в заранее выделенном массиве
Стандартный
std::vector использует placement new внутри себя! 🟠Кастомные аллокаторы (`std::allocator`)
Например, в играх и в embedded-разработке, где управление памятью критично.
🚩`placement new` и классы
Если объект – это класс,
placement new вызывает его конструктор в выделенной памяти. #include <iostream>
#include <cstdlib> // Для malloc/free
class MyClass {
public:
int x;
MyClass(int val) : x(val) { std::cout << "Конструктор!\n"; }
~MyClass() { std::cout << "Деструктор!\n"; }
};
int main() {
void* buffer = malloc(sizeof(MyClass)); // Выделяем сырую память
MyClass* obj = new (buffer) MyClass(42); // Размещаем объект
std::cout << "Значение: " << obj->x << std::endl;
obj->~MyClass(); // Ручной вызов деструктора!
free(buffer); // Освобождаем память
}
Вывод
Конструктор!
Значение: 42
Деструктор!
🚩Ошибки при `placement new`
Забыл вызвать деструктор
MyClass* obj = new (buffer) MyClass(10);
// delete obj; // НЕЛЬЗЯ! Обычный `delete` не работает
free(buffer); // Память утекла! Деструктор не вызвался
Нужно вызвать вручную
obj->~MyClass();
free(buffer);
placement new в одном буфере несколько раз (без очистки)*void* buffer = malloc(sizeof(MyClass));
MyClass* obj1 = new (buffer) MyClass(1);
MyClass* obj2 = new (buffer) MyClass(2); // Перезапишет obj1!
Нужно сначала вызвать деструктор
obj1->~MyClass();
MyClass* obj2 = new (buffer) MyClass(2);
Освободил память перед вызовом деструктора
free(buffer); // Память освободили
obj->~MyClass(); // ОШИБКА! Память уже не существует
Правильный порядок
obj->~MyClass();
free(buffer);
Ставь 👍 и забирай 📚 Базу знаний