Как делают Вы копируете содержание массива к станд.:: вектор в C++ без цикличного выполнения?

107
задан phoenix 10 March 2017 в 15:32
поделиться

9 ответов

Если можно создать вектор после того, как Вы получили массив и выстраиваете размер, можно просто сказать:

std::vector<ValueType> vec(a, a + n);

... принятие a является Вашим массивом, и n число элементов, которое это содержит. Иначе std::copy() w / resize() добьется цели.

я избегал бы memcpy(), если Вы не можете быть уверены, что значения являются типами простых данных (POD).

кроме того, стоящий замечания, что ни один из них действительно не избегает для цикла - это - просто вопрос того, необходимо ли видеть его в коде или нет. O (n) производительность во время выполнения неизбежно для копирования значений.

Наконец, обратите внимание, что массивы C-стиля являются совершенно допустимыми контейнерами для большинства алгоритмов STL - необработанный указатель эквивалентен begin(), и (ptr + n) эквивалентно end().

104
ответ дан phoenix 24 November 2019 в 03:34
поделиться

Если все, что Вы делаете, заменяет существующие данные, то можно сделать это

std::vector<int> data; // evil global :)

void CopyData(int *newData, size_t count)
{
   data.assign(newData, newData + count);
}
33
ответ дан Torlack 24 November 2019 в 03:34
поделиться

Было много ответов здесь, и примерно все они сделают задание.

Однако существует некоторый вводящий в заблуждение совет!

Вот опции:

vector<int> dataVec;

int dataArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
unsigned dataArraySize = sizeof(dataArray) / sizeof(int);

// Method 1: Copy the array to the vector using back_inserter.
{
    copy(&dataArray[0], &dataArray[dataArraySize], back_inserter(dataVec));
}

// Method 2: Same as 1 but pre-extend the vector by the size of the array using reserve
{
    dataVec.reserve(dataVec.size() + dataArraySize);
    copy(&dataArray[0], &dataArray[dataArraySize], back_inserter(dataVec));
}

// Method 3: Memcpy
{
    dataVec.resize(dataVec.size() + dataArraySize);
    memcpy(&dataVec[dataVec.size() - dataArraySize], &dataArray[0], dataArraySize * sizeof(int));
}

// Method 4: vector::insert
{
    dataVec.insert(dataVec.end(), &dataArray[0], &dataArray[dataArraySize]);
}

// Method 5: vector + vector
{
    vector<int> dataVec2(&dataArray[0], &dataArray[dataArraySize]);
    dataVec.insert(dataVec.end(), dataVec2.begin(), dataVec2.end());
}

, Короче говоря, Метод 4, с помощью вектора:: вставьте, является лучшим для сценария bsruth.

Вот некоторые окровавленные детали:

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

Метод 2 является предложенным повышением производительности к Методу 1; просто предварительно зарезервируйте размер массива прежде, чем добавить его. Для больших массивов это могло бы справка. Однако лучший совет здесь никогда не состоит в том, чтобы использовать резерв, если профилирование не предполагает, что можно быть в состоянии получить улучшение (или необходимо удостовериться, что итераторы не будут недействительными). Bjarne соглашается . Кстати, я нашел, что этот метод работал самый медленный большую часть времени, хотя я изо всех сил пытаюсь всесторонне объяснить, почему это регулярно было значительно медленнее, чем метод 1...

Метод 3 является старым школьным решением - бросают некоторый C в проблему! Хорошо работает и быстро для типов POD. В этом случае измените размеры, требуется, чтобы быть названным с тех пор memcpy работы вне границ вектора и нет никакого способа сказать вектору, что его размер изменился. Кроме того, чтобы быть ужасным решением (байт, копирующий!) помнят, что это может только использоваться для типов POD . Я никогда не использовал бы это решение.

Метод 4 является лучшим способом пойти. Это означает, ясно, это является (обычно) самым быстрым, и это работает на любые объекты. Нет никакой оборотной стороны к использованию этого метода для этого приложения.

Метод 5 является тонкой настройкой на Методе 4 - копируют массив в вектор и затем добавляют его. Хороший вариант - обычно быстрый выход и ясный.

Наконец, Вы знаете, что можно использовать векторы вместо массивов, правильно? Даже когда функция ожидает массивы c-стиля, можно использовать векторы:

vector<char> v(50); // Ensure there's enough space
strcpy(&v[0], "prefer vectors to c arrays");

Hope, которая помогает кому-то там!

202
ответ дан MattyT 24 November 2019 в 03:34
поделиться

станд.:: копия - то, что Вы ищете.

11
ответ дан luke 24 November 2019 в 03:34
поделиться

Так как я могу только отредактировать свой собственный ответ, я собираюсь сделать составной ответ от других ответов до моего вопроса. Благодаря всем Вам, кто ответил.

Используя станд.:: копия , это все еще выполняет итерации в фоновом режиме, но Вы не должны выводить код.

int foo(int* data, int size)
{
   static std::vector<int> my_data; //normally a class variable
   std::copy(data, data + size, std::back_inserter(my_data));
   return 0;
}

Используя регулярный memcpy. Это, вероятно, лучше всего используется для типов основных данных (т.е. интервал), но не для более сложных матриц структур или классов.

vector<int> x(size);
memcpy(&x[0], source, size*sizeof(int));
7
ответ дан bsruth 24 November 2019 в 03:34
поделиться

избегайте memcpy, говорю я. Никакая причина смешать с операциями указателя, если Вы действительно не имеете к. Кроме того, это будет только работать на типы POD (как интервал), но перестало бы работать, если Вы будете иметь дело с типами, которые требуют конструкции.

3
ответ дан Assaf Lavie 24 November 2019 в 03:34
поделиться

В дополнение к методикам, представленным выше, необходимо удостовериться, что Вы используете любой станд.:: Vector.reserve (), станд.:: Vector.resize (), или конструкция вектор к размеру, для проверки вектора имеет достаточно элементов в нем для содержания данных. в противном случае Вы повредите память. Это верно для любого станд.:: копия () или memcpy ().

Это - причина использовать вектор push_back (), Вы не можете записать мимо конца вектора.

1
ответ дан Thomas Jones-Low 24 November 2019 в 03:34
поделиться

Еще один ответ, так как человек сказал, "Что я не знаю, сколько раз будет вызвана моя функция", Вы могли использовать векторный метод вставки как так для добавления массивов значений до конца вектора:

vector<int> x;

void AddValues(int* values, size_t size)
{
   x.insert(x.end(), values, values+size);
}

мне нравится этот путь, потому что реализация вектора должна быть в состоянии оптимизировать для лучшего способа вставить значения на основе типа итератора и самого типа. Вы несколько отвечаете на реализации stl.

, Если бы необходимо гарантировать самую быструю скорость и Вы знаете, что Ваш тип является типом POD тогда, я рекомендовал бы изменять размеры метод в ответе Thomas:

vector<int> x;

void AddValues(int* values, size_t size)
{
   size_t old_size(x.size());
   x.resize(old_size + size, 0);
   memcpy(&x[old_size], values, size * sizeof(int));
}
2
ответ дан Shane Powell 24 November 2019 в 03:34
поделиться

Принятие Вас знает, насколько большой объект в векторе:

std::vector<int> myArray;
myArray.resize (item_count, 0);
memcpy (&myArray.front(), source, item_count * sizeof(int));

http://www.cppreference.com/wiki/stl/vector/start

0
ответ дан Thomas Jones-Low 24 November 2019 в 03:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: