Ответ 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
и т.д. или пытающиеся изобрести колесо.