сжатие вектора

У меня проблема с движком ландшафта (использующим DirectX).

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

НО, когда блок уменьшается в деталях, вектор не уменьшается в размерах.

Итак, мой вопрос: есть ли способ уменьшить размер вектора? Я пробовал это:

vertexvector.reserve(16);

Ответов (4)

Решение

Обычный трюк - поменять местами пустой вектор:

vector<vertex>(vertexvector.begin(), vertexvector.end()).swap(vertexvector);

Если вы извлекаете элементы из вектора, это не освобождает память (потому что это сделало бы недействительными итераторы в элементах контейнера). Вы можете скопировать вектор в новый вектор, а затем поменять его местами с оригиналом. Это позволит не тратить впустую место. Swap имеет постоянную временную сложность, потому что обмен не должен делать недействительными итераторы для элементов замененных векторов: поэтому он должен просто обмениваться указателями внутреннего буфера.

vector<vertex>(a).swap(a);

Это известно как идиома «усаживаемая по размеру». Между прочим, следующая версия C++ включает функцию-член shrink_to_fit () для std::vector.

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

  1. Попросите у распределителя новую, меньшую по размеру ячейку памяти,
  2. Скопируйте содержимое из старого места и
  3. Скажите распределителю освободить старую область памяти.

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

Если у вас произошло очень большое изменение требуемого размера, и вы знаете, что не хотите, чтобы этот вектор снова расширялся (принцип местоположения предполагает, что вы это сделаете, но, конечно, есть исключения), тогда вы можете использовать предложенный litb операция swap для явного сжатия вашего вектора:

vector<vertex>(a).swap(a);

Для этого есть функция-член shrink_to_fit. Он более эффективен, чем большинство других методов, поскольку он выделяет новую память и копирует только в случае необходимости. Подробности обсуждаются здесь. Является ли shrink_to_fit правильным способом уменьшения емкости std::vector до его размера?

Если вы не возражаете, что функции распределения libc, realloc еще более эффективен, он не будет копировать данные на сжатие, просто пометьте дополнительную память как свободную, и если вы увеличиваете память, и память свободна после того, как она отметит необходимые память как используется, а не копировать. Однако будьте осторожны, вы переходите из шаблонов C++ stl в указатели void C и должны понимать, как работают указатели и управление памятью, что многие не одобряют в настоящее время как источник ошибок и утечек памяти.