C ++: выделить блок T без вызова конструктора - PullRequest
25 голосов
/ 05 марта 2010

Я не хочу вызывать конструктор. Я использую новое место размещения.

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

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

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

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

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

Ответы [ 3 ]

25 голосов
/ 05 марта 2010

Во-первых, вы не выделяете «блок из 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 и т. Д. Или попытаться заново изобрести колесо.

6 голосов
/ 05 марта 2010

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

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

1 голос
/ 05 марта 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...