Страницы

Поиск по вопросам

четверг, 20 декабря 2018 г.

Явный вызов конструктора для объекта

Как создать объект в динамической памяти используя malloc()? Нужно ведь явно вызывать конструктор, как это сделать?


Ответ

Вам нужен placement new.
Например, так:
void* place = malloc(sizeof(Object)); Object* o = new(place) Object();
Не забудьте в конце вызвать и деструктор вручную:
o->~Object();
и если нужно
free(place);
Документация: https://isocpp.org/wiki/faq/dtors#placement-new

Для случая, когда у вас память выделена заранее, вам придётся позаботиться о выравнивании. Обычный указатель, который возвращает malloc, имеет выравнивание, достаточное для нормально объявленного класса, то есть, класса, определение которого не содержит alignas() (а также определение классов его полей), и значит, ничего больше делать не нужно.
Если это (отсутствие alignas) не гарантировано, у вас есть два пути. Вы можете вместо malloc использовать aligned_alloc (или _aligned_malloc на старых версиях Visual Studio), который выдаёт malloc с нужным выравниванием:
void* place = std::aligned_alloc(alignof(Object), sizeof(Object)); void* place = _aligned_malloc(sizeof(Object), alignof(Object));
(да, порядок противоположный).
Или если вам нужен именно malloc, то можно заказать больше памяти для того, чтобы было место для выравнивания, и выровнять указатель при помощи std::align
std::size_t alloc_size = sizeof(Object) + alignof(Object) - 1; void* place = malloc(alloc_size); void* aligned_place = place; if (std::align(alignof(Object), sizeof(Object), aligned_place, alloc_size)) { Object* o = new(aligned_place) Object(); // ... }
Эта вторая техника пригодится, если вы захотите выделить в одном буфере несколько объектов.

Комментариев нет:

Отправить комментарий