уменьшить емкость stl-вектора

Есть ли способ уменьшить емкость вектора?

Мой код вставляет значения в вектор (не зная их номер заранее), и когда это заканчивается, векторы используются только для операций чтения.

Я думаю, я мог бы создать новый вектор, сделать .reseve () с размером и скопировать элементы, но мне не очень нравится дополнительная операция копирования.

PS: Я не забочусь о портативном решении, если он работает для gcc.

std::vector(v).swap(v); 

Обмен содержимым с другим вектором меняет емкость.

  std::vector(v).swap(v); ==> is equivalent to std::vector tmp(v); // copy elements into a temporary vector v.swap(tmp); // swap internal vector data 

Swap () изменит только внутреннюю структуру данных.

С C ++ 11 вы можете вызвать функцию-член shrink_to_fit() . В проекте стандартного раздела 23.2.6.2 говорится:

shrink_to_fit – это необязательный запрос для уменьшения capacity() до size() . [Примечание. Запрос не является обязательным, чтобы разрешить широту для конкретных реализаций. -End note]

Посмотрите на Скотта Мейерса Эффективный элемент STL 17.

В основном вы не можете напрямую уменьшить размер хранилища std::vector . resize() и reseve() никогда не уменьшат фактический объем памяти контейнера. «Трюк» состоит в том, чтобы создать новый контейнер нужного размера, скопировать данные и обменять их с помощью текущего контейнера. Если мы хотим очистить контейнер, это просто:

 std::vector().swap(v); 

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

 std::vector(v).swap(v); 

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

Идиоматическое решение состоит в том, чтобы заменить новый вектор.

 vector().swap(v); 

Изменить: я неправильно понял вопрос. Приведенный выше код очистит вектор. OP хочет сохранить элементы нетронутыми, только усадочная capacity() до size() .

Трудно сказать, сделает ли это код. Я сомневаюсь, что есть портативное решение. Для gcc вам нужно взглянуть на их конкретную реализацию vector .

edit : Итак, я заглянул в реализацию libstdc ++. Кажется, что решение aJ действительно будет работать.

 vector(v).swap(v); 

См. Источник , строка 232.

Нет, вы не можете уменьшить емкость вектора без копирования. Тем не менее, вы можете контролировать, сколько нового роста распределения, проверяя емкость () и резерв вызовов () каждый раз, когда вы что-то вставляете. Поведение по умолчанию для std :: vector должно увеличивать его емкость в 2 раза каждый раз, когда требуется новая емкость. Вы можете развить его по своему собственному магическому отношению:

 template  void myPushBack(std::vector& vec, const T& val) { if (vac.size() + 1 == vac.capacity()) { vac.reserve(vac.size() * my_magic_ratio); } vec.push_back(val); } 

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

Я не говорю, что GCC не может иметь какой-либо метод для выполнения того, что вы хотите без копии, но было бы сложно реализовать (я думаю), потому что векторам необходимо использовать объект Allocator для выделения и освобождения памяти, а интерфейс для Allocator не включает метод reallocate() . Я не думаю, что это невозможно сделать, но это может быть сложно.

Если вы беспокоитесь о накладных расходах вашего вектора, то, возможно, вы должны искать другой тип структуры данных. Вы упомянули, что как только ваш код будет завершен, инициализация вектора становится процессом только для чтения. Я бы посоветовал пойти с открытым массивом, который позволит программе определять свои возможности во время компиляции. Или, возможно, связанный список будет более подходящим для ваших нужд.
Лемме знаю, полностью ли я неправильно понял, к чему ты клонился.

-UBcse

Старая нить, я знаю, но в случае, если кто-то это просмотрит в будущем .. в C ++ 11 есть shrink_to_fit (), но поскольку это запрос без привязки, поведение будет зависеть от его реализации.

См .: http://en.cppreference.com/w/cpp/container/vector/shrink_to_fit

Получите книгу «Эффективный STL» Скотта Майерса. У этого есть полный пункт jus об уменьшении емкости вектора.

  • Ли вектор :: erase () на векторе указателей объектов уничтожает сам объект?
  • Удалить элементы вектора внутри цикла
  • Альтернатива вектору
  • Инициализация вектора ublas из массива C
  • std :: vector :: resize () vs. std :: vector :: reserve ()
  • У std :: vector * есть * для перемещения объектов при увеличении емкости? Или, могут ли распределители «перераспределять»?
  • вектор против списка в STL
  • Как использовать std :: sort с вектором структур и функцией сравнения?
  • Почему std :: vector :: operator от 5 до 10 раз быстрее, чем std :: vector :: at ()?
  • C ++ for-loop - size_type vs. size_t
  • VBOs с std :: vector
  • Interesting Posts

    Как запустить DISM для локального источника?

    Sublime text 2 command create link, но команда пуста

    Проблема NASM в 64-разрядной версии OSX

    Как объявить массив, когда я не знаю длину до времени выполнения?

    Использование терминала Linux / Unix для копирования многих файлов в новое место

    Как программно печатать в PDF-файл без запроса имени файла в C # с помощью принтера Microsoft Print To PDF, который поставляется с Windows 10

    Android / Java – Опубликовать простой текст на стене Facebook?

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

    Как использовать Moq для издевательства над методом расширения?

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

    Значок меню параметров Android не будет отображаться

    Как узнать, когда обновляется веб-страница?

    Vista – вытертый MBR и HEAD диска – как восстановить?

    Как установить фоновый backgroundRadius для NSString на iOS7

    как получить сообщение при получении уведомления «kCTMessageReceivedNotification» на IOS5

    Давайте будем гением компьютера.