Изменение размера std :: vector без уничтожения элементов

Я использую все время одно и то же std::vector<int> для того, чтобы попытаться избежать выделения сделки все время. В нескольких строках мой код выглядит следующим образом:

std::vector<int> myVector;
myVector.reserve(4);

for (int i = 0; i < 100; ++i) {
fillVector(myVector);
//use of myVector
//....
myVector.resize(0);
}

В каждой итерации, myVector будет заполнено до 4 элементов. Для того, чтобы сделать эффективный код, я хочу использовать всегда myVector, Однако в myVector.resize() элементы в myVector разрушаются. Я это понимаю myVector.clear() будет иметь тот же эффект.

Я думаю, если бы я мог просто перезаписать существующие элементы в myVector Я мог бы сэкономить время. Однако я думаю, что std::vector не способен сделать это.

Есть ли способ сделать это? Имеет ли смысл создавать доморощенную реализацию, которая перезаписывает элементы?

3

Решение

std :: vector не является решением в этом случае. Вы не хотите изменить размер / очистить / (де) выделить заново? Не.

  1. fillVector () заполняет vector с количеством элементов, известных в каждой итерации.
  2. Вектор внутренне представлен как непрерывный блок памяти типа T *.
  3. Вы не хотите (де) выделять память каждый раз.

Хорошо. Используйте простую структуру:

struct upTo4ElemVectorOfInts
{
int data[4];
size_t elems_num;
};

И измените fillVector (), чтобы сохранить дополнительную информацию:

void fillVector(upTo4ElemVectorOfInts& vec)
{
//fill vec.data with values
vec.elems_num = filled_num; //save how many values was filled in this iteration
}

Используйте это так же:

upTo4ElemVectorOfInts myVector;

for (int i = 0; i < 100; ++i)
{
fillVector(myVector);
//use of myVector:
//- myVector.data contains data (it's equivalent of std::vector<>::data())
//- myVector.elems_num will tell you how many numbers you should care about
//nothing needs to be resized/cleared
}

Дополнительное примечание:

Если вы хотите более общее решение (для работы с любым типом или размером), вы можете, конечно, использовать шаблоны:

template <class T, size_t Size>
struct upToSizeElemVectorOfTs
{
T data[Size];
size_t elems_num;
};

и настройте fillVector () для принятия шаблона вместо известного типа.

Это решение, вероятно, самое быстрое. Вы можете подумать: «Эй, а если я захочу заполнить до 100 элементов? 1000? 10000? Что тогда? 10000-элементный массив будет занимать много памяти!».
Это все равно потребляет. Vector автоматически изменяет размеры, и это перераспределяется вне вашего контроля и, следовательно, может быть очень неэффективным. Если ваш массив достаточно мал и вы можете предсказать максимальный требуемый размер, всегда используйте хранилище фиксированного размера, созданное в локальном стеке. Это быстрее, эффективнее и проще. Конечно, это не будет работать для массивов из 1.000.000 элементов (вы получите Переполнение стека в этом случае).

-1

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

Ваш код уже действителен (myVector.clear() имеет лучший стиль, чем myVector.resize(0) хоть).

int int destructor ничего не делает.
Так resize(0) просто устанавливает size до 0, capacity нетронутым

5

Просто не продолжайте изменять размер myVector, Вместо этого инициализируйте его с 4 элементами (с std::vector<int> myVector(4)) и просто назначьте элементам (например, myVector[0] = 5).

Однако, если он всегда будет фиксированного размера, вы можете использовать std::array<int, 4>,

4

Изменение размера вектора до 0 не уменьшит свою емкость и, так как ваш тип элемента intнет деструкторов для запуска:

#include <iostream>
#include <vector>

int main() {
std::vector<int> v{1,2,3};
std::cout << v.capacity() << ' ';
v.resize(0);
std::cout << v.capacity() << '\n';
}

// Output: 3 3

Поэтому ваш код уже работает в основном оптимально; единственная дополнительная оптимизация, которую вы могли бы сделать, это избежать изменения размера полностью, тем самым теряя внутренний «установить размер на 0» внутри std::vector что, вероятно, сводится к if заявление и изменение значения элемента данных.

3

На самом деле то, что у вас есть в настоящее время

for (int i = 0; i < 100; ++i) {
myVector.reserve(4);
//use of myVector
//....
myVector.resize(0);
}

Я не вижу никакого смысла в этом коде.

Конечно, было бы лучше использовать myVector.clear() вместо myVector.resize(0);

Если вы всегда перезаписываете ровно 4 элемента вектора внутри цикла, вы можете использовать

std::vector<int> myVector( 4 );

вместо

std::vector<int> myVector;
myVector.reserve(4);

при условии, что функция fillVector (myVector); использует оператор индекса для доступа к этим 4 элементам вектора вместо функции-члена push_back

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

0
По вопросам рекламы [email protected]