C ++ с использованием массива без вызова конструктора

Моя задача — создать массив типов шаблонов без вызова конструктора T (шаблон). После этого я хочу переместить одно значение в этот массив из другого с помощью std :: move. Как я могу сделать это в C ++? Вот мой код:

void *temp = malloc((end-begin) * sizeof(T));
for (unsigned int i = begin; i < end; ++i){
temp[i] = std::move(array[i]);
}

Но это не работа. Компилятор говорит следующее: Индекс указателя на неполный тип ‘void’.

1

Решение

Массив void не имеет смысла. void является неполным типом (и не имеет размера), поэтому temp[i] генерирует ошибку, которую вы видите.

Чтобы достичь того, что вы хотите сделать, почему бы не использовать std::vector, и вставлять в него предметы по мере их появления?

std::vector<T> temp;
for (unsigned int i = begin; i < end; ++i){
temp.push_back(std::move(array[i]));
}
2

Другие решения

Если вы действительно хотите сделать это вручную, вы ищете размещение нового. Сначала вы выделяете «сырой буфер» unsigned chars:

unsigned char* buf = new unsigned char(end-begin);

или же:

auto buf = std::make_unique<unsigned char[]>(end-begin);

а потом ты пишешь такие вещи, как new (buf) T, new (buf+sizeof(T)) T, new (buf+2*sizeof(T)) T «поместить» ваши объекты в это пространство памяти.

Проблема в том, что в приведенном выше примере я полностью проигнорировал требования выравнивания, что опасно.

Таким образом, вместо того, чтобы реплицировать, какие пулы памяти и std::vector делай, просто используй std::vector!

std::vector<T> vec;
vec.reserve(end-begin);
for (unsigned int i = begin; i < end; ++i){
vec.push_back(std::move(array[i]);
}

и вы сделали.

1

Как указывают другие void не имеет определенного размера, так void* не может быть проиндексирован как массив.

Где же temp[1] начать?

Наивное исправление:

T *temp = std::malloc((end-begin) * sizeof(T));

Так же плохо, когда используется в сочетании с:

temp[i] = std::move(array[i]);

Этот код будет вызывать оператор присваивания, и, если нетривиально, произойдет сбой при работе с мусором, который находится в temp[i], Например, если назначение явно или неявно отменяет выделение ресурсов в цели назначения, оно будет работать с неинициализированным temp[i] и потерпеть неудачу.

Если (ЕСЛИ!) Вы сделали это, правильный код будет:

std::memcpy(temp+i*sizeof(i),array[I],sizeof(T));

Эта строка кода по существу предполагает, что T является тривиально копируемым типом.

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

Так что рекомендуемый код (используя for цикл) это:

T* temp= new T[end-being];
for(unsigned int i=begin;i<end;++i){
temp[i-begin]=array[i];
}

Примечание: этот код также исправляет ошибку в исходном коде, которая ломается, когда begin!=0,
Код, похоже, копирует подраздел из середины array к началу temp но забывает начать с индекса 0 из temp,

Но рекомендуемый подход C ++ к такому копированию:

T* temp= new T[end-being];
std::copy(array+begin,array+end,temp);

Хорошие реализации будут определять и использовать любые объемные операции с памятью, где это возможно.
Так что неявно это должно привести к std::memmove(temp,array,(end-begin)*sizeof(T)); если действительный.

Единственный последний поворот, который компилятор может не распознать, это то, что потенциально немного более эффективный

std::memcpy(temp,array,(end-begin)*sizeof(T));

На самом деле действительно в этом случае, потому что мы знаем temp не может пересекаться с array (не говоря уже о копируемом диапазоне).

Сноска. Как отмечалось в комментариях, самый обычный подход C ++ заключается в использовании std::vector который обычно можно предположить, что он использует эти оптимизации за кулисами. Однако, если по какой-то причине реорганизация приложения невозможна или нежелательна, этот ответ предоставляет действительный эффективный способ переписать предоставленный код.

0

Пытаться

T *temp = (T*) malloc((end-begin) * sizeof(T));
-1
По вопросам рекламы [email protected]