Подтвердить что ты не робот

С++: выделить блок из T без вызова конструктора

Мне не нужен конструктор. Я использую новое размещение.

Я просто хочу выделить блок из T.

Мой стандартный подход:

T* data = malloc(sizeof(T) * num);

однако, я не знаю, является ли (data + i) T-выровненным. Кроме того, я не знаю, является ли это правильным способом "С++".

Как я должен выделить блок из T без вызова его конструктора?

4b9b3361

Ответ 1

Во-первых, вы не выделяете "блок T*". Вы выделяете "блок T".

Во-вторых, если ваш T имеет нетривиальный конструктор, то до тех пор, пока не будут созданы элементы, ваш блок на самом деле не является "блоком Т", а скорее блоком необработанной памяти. Здесь вообще нет смысла включать T (кроме вычисления размера). Указатель void * более уместен с необработанной памятью.

Чтобы выделить память, вы можете использовать все, что вам нравится.

void *raw_data = malloc(num * sizeof(T));

или

void *raw_data = new unsigned char[num * sizeof(T)];

или

void *raw_data = ::operator new(num * sizeof(T));

или

std::allocator<T> a;
void *raw_data = a.allocate(num);
// or
// T *raw_data = a.allocate(num);

Позже, когда вы на самом деле создаете элементы (используя новое место размещения, как вы сказали), вы, наконец, получите значащий указатель типа T *, но пока память не является сырой, использование T * делает мало (хотя это не ошибка).

Если ваш T не имеет каких-либо требований к экзотическому выравниванию, память, возвращаемая вышеуказанными функциями распределения, будет правильно выровнена.

На самом деле вы можете взглянуть на утилит памяти, предоставляемых стандартной библиотекой С++: std::allocator<> с методами allocate и construct, а также алгоритмы как uninitialized_fill и т.д. или пытающиеся изобрести колесо.

Ответ 2

Возврат из malloc выравнивается для любого типа, поэтому это не проблема.

Как правило, в С++ предпочтительным будет ::operator new. Вы также можете рассмотреть возможность использования Allocator<T>, что дает дополнительную гибкость (например, возможность легко переключать распределители.

Ответ 3

T* data = reinterpret_cast<T*>(operator new(sizeof(T) * num));

Или просто используйте std::vector<T> и не беспокойтесь об этих деталях памяти низкого уровня;)