Я не хочу вызванного конструктора. Я использую новое размещение.
Я просто хочу выделить блок T.
Мой стандартный подход:
T* data = malloc(sizeof(T) * num);
однако, я не знаю, является ли (data+i) T-aligned. Кроме того, я не знаю, является ли это правильный "C++" путь.
Как я должен выделить блок T, не вызывая его конструктора?
Во-первых, вы не выделяете «блок из T *
». Вы выделяете «блок из 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
не имеет некоторых экзотических требований к выравниванию, память, возвращаемая вышеуказанными функциями распределения, будет правильно выровнена.
Возможно, вам действительно захочется взглянуть на утилиты памяти, предоставляемые стандартной библиотекой C ++: std :: allocator <>
с методами allocate
и construct
, а также алгоритмы типа uninitialized_fill
и т. д. или попытки изобретать велосипед.
T* data = reinterpret_cast
Или просто используйте std::vector
и не беспокойтесь об этих низкоуровневых деталях памяти ;)
Возврат из malloc
выровнен для любого типа, так что это не проблема.
Обычно в C ++ предпочтительнее использовать :: operator new
. Вы также можете рассмотреть возможность использования Allocator
, который дает некоторую дополнительную гибкость (например, возможность легко переключать распределители.