Placement new
Оператор placement new - это специальная форма оператора new,
которая не выделяет новую память, а создаёт объект в уже
существующем буфере по указанному адресу. В первом параметре
мы передаём указатель на область памяти, где должен быть размещён
объект, а в последующих параметрах - аргументы для конструктора
создаваемого объекта. Такой подход используется, например,
в контейнерах STL, пулах памяти и при работе с буферами
фиксированного размера.
Синтаксис
new (address) Type(args);
Здесь address - указатель на уже выделенную память,
Type - тип создаваемого объекта, args -
аргументы конструктора.
Пример
Давайте разместим объект типа int со значением 42
в заранее подготовленном буфере:
#include <iostream>
#include <new>
using namespace std;
int main()
{
alignas(int) char buffer[sizeof(int)];
int* p = new (buffer) int(42);
cout << *p << endl;
return 0;
}
Результат выполнения кода:
42
Пример
Давайте разместим объект пользовательского класса в буфере и вызовем его метод:
#include <iostream>
#include <new>
using namespace std;
class Point
{
public:
int x;
int y;
Point(int x, int y) : x(x), y(y) {}
void print()
{
cout << x << " " << y << endl;
}
};
int main()
{
alignas(Point) char buffer[sizeof(Point)];
Point* p = new (buffer) Point(1, 2);
p->print();
p->~Point();
return 0;
}
Результат выполнения кода:
1 2
Пример
Поскольку placement new не выделяет память, освобождать
её оператором delete нельзя - деструктор следует вызывать
явно. Давайте продемонстрируем это на массиве объектов:
#include <iostream>
#include <new>
using namespace std;
class Value
{
public:
int v;
Value(int v) : v(v)
{
cout << "construct " << v << endl;
}
~Value()
{
cout << "destroy " << v << endl;
}
};
int main()
{
alignas(Value) char buffer[sizeof(Value) * 2];
Value* a = new (buffer) Value(1);
Value* b = new (buffer + sizeof(Value)) Value(2);
cout << a->v << " " << b->v << endl;
a->~Value();
b->~Value();
return 0;
}
Результат выполнения кода:
"construct 1"
"construct 2"
1 2
"destroy 1"
"destroy 2"
Смотрите также
-
оператор
new,
который выделяет память под объект -
оператор
delete,
который освобождает память объекта -
функция
destroy_at,
которая явно вызывает деструктор объекта -
функция
construct_at,
которая создаёт объект в заданной памяти