Во-первых, вы не выделяете «блок из 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);
Позже, когда вы на самом деле создаете элементы (используя, как вы сказали, размещение new), вы, наконец, получите значимый указатель типа T *
, но пока память не заполнена, использование T *
делает мало смысл (хотя это не ошибка).
Если ваш T
не имеет каких-либо экзотических требований к выравниванию, память, возвращенная вышеупомянутыми функциями выделения, будет правильно выровнена.
Возможно, вы захотите взглянуть на утилиты памяти, предоставляемые стандартной библиотекой C ++: std::allocator<>
с методами allocate
и construct
, а алгоритмы вместо uninitialized_fill
и т. Д. Или попытаться заново изобрести колесо.