Как создать массив в стиле C без вызова конструкторов по умолчанию? - PullRequest
5 голосов
/ 16 февраля 2010

Я пишу класс шаблона управления памятью, в котором я хочу создать массив в стиле C фиксированного размера, который будет служить кучей. Я сохраняю объекты в массиве так:

T v[SIZE];

Поскольку это только выполняет роль кучи, которая может содержать объекты T, я не хочу, чтобы конструктор по умолчанию T автоматически вызывался для каждого объекта в массиве.

Я думал о решении определить кучу следующим образом:

char v[SIZE * sizeof(T)];

... но это вызовет проблемы с выравниванием.

Есть ли лучший способ добиться этого?

ДОБАВИТЬ: Поскольку у меня есть особые требования времени выполнения, важно, чтобы этот класс не делал никаких распределений в глобальной куче.

ADD 2: SIZE - это аргумент шаблона, который известен во время компиляции.

Ответы [ 6 ]

6 голосов
/ 16 февраля 2010

Стандартные контейнеры используют распределители для отделения выделения / освобождения от строительства / разрушения. Стандартная библиотека предоставляет один распределитель, который выделяется в куче.

Этот код объявляет массив, достаточно большой для размещения SIZE элементов типа T с правильным выравниванием:

typedef typename std::tr1::aligned_storage<sizeof(T),std::tr1::alignment_of<T>::value>::type aligned_storage;
aligned_storage array[SIZE];

Решение, использующее std::allocator, не может быть использовано для объявления массива в стеке, и поскольку стандартные контейнеры требуют, чтобы пользовательские распределители не содержали состояния, пользовательский распределитель нельзя переносить для размещения в стеке. .

Если ваш компилятор не поддерживает std::tr1::alignment_of, вы можете использовать boost::alignment_of.

2 голосов
/ 16 февраля 2010

То, что вы ищете, называется Allocator . Хороший обзор можно найти здесь: http://www.codeproject.com/KB/cpp/allocator.aspx

0 голосов
/ 17 февраля 2010

Как я, вероятно, сделаю это (после просмотра реализации EASTL fixed_vector):

PRAGMA_PRE_ALIGN(sizeof(T)) char[SIZE * sizeof(T)]; PRAGMA_POST_ALIGN(sizeof(T))

... и реализовать макросы PRAGMA_PRE_ALIGN и PRAGMA_POST_ALIGN, специфичные для компилятора, которые вставляют правильные # прагмы.

К сожалению, boost и tr1 для этого проекта невозможны.

0 голосов
/ 17 февраля 2010

Вы можете использовать структуру для обработки проблемы выравнивания.

struct Tbuffer { char data_[ sizeof( T ) ]; }

struct Tbuffer heap[ SIZE ];
0 голосов
/ 16 февраля 2010

Что я, вероятно, сделаю, это создаю массив char (примерно как вы уже рассмотрели), но выделите достаточно места для еще одного объекта, чем вам действительно нужно. Затем вам нужно будет написать немного кода, чтобы найти правильное выравнивание для ваших объектов в этом пространстве.

Самым большим требованием выравнивания для объекта является его собственный размер (в противном случае массивы этих объектов не могут быть смежными, что необходимо). Следовательно, вы выбираете первый адрес в char-буфере, кратный sizeof (T), и начинаете свой массив оттуда.

0 голосов
/ 16 февраля 2010

Странно, но должно работать:

long long v[size * sizeof(T)/sizeof(long long)+1];

Этот буфер будет выравниваться на 64 бита.Но лучше будет выделить память на new.

В любом случае, если size является переменной - компилятор будет выделять память динамически через malloc / new (а не в стеке).

РЕДАКТИРОВАТЬ: Вы не можете использовать std::auto_ptr для автоматического освобождения буфера.Вместо scoped_arr от повышения можно использовать

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