Уменьшить емкость stl-вектора
Есть ли способ уменьшить емкость вектора?
Мой код вставляет значения в вектор (не зная их номера заранее) и
когда это заканчивается, векторы используются только для операций чтения.
Я думаю, я мог бы создать новый вектор, сделать .reseve() с размером и копией
элементы, но мне не очень нравится дополнительная операция копирования.
PS: Я не забочусь о переносном решении, если оно работает для gcc.
Ответы
Ответ 1
std::vector<T>(v).swap(v);
Обмен содержимым с другим вектором меняет емкость.
std::vector<T>(v).swap(v); ==> is equivalent to
std::vector<T> tmp(v); // copy elements into a temporary vector
v.swap(tmp); // swap internal vector data
Swap() изменит только внутреннюю структуру данных.
Ответ 2
С С++ 11 вы можете вызвать функцию-член shrink_to_fit()
. проект стандарта в разделе 23.2.6.2 гласит:
shrink_to_fit
является необязательным запросом для уменьшения capacity()
до size()
. [Примечание: запрос не является обязательным для разрешить широту для оптимизация реализации. -end note]
Ответ 3
Посмотрите на Скотта Мейерса Эффективный элемент STL 17.
В принципе, вы не можете напрямую уменьшить размер хранилища std::vector. Изменение размера и reseve никогда не уменьшит фактический объем памяти контейнера. "Трюк" состоит в том, чтобы создать новый контейнер нужного размера, скопировать данные и обменять их с помощью текущего контейнера. Если мы хотим очистить контейнер, это просто:
std::vector<T>().swap(v);
Если нам нужно скопировать данные, то нам нужно сделать копию:
std::vector<T>(v).swap(v);
То, что это делает, создает новый вектор с данными из старого, делая копию, которая потребуется в любой операции, которая имеет необходимый эффект. Затем вызов swap будет просто заменять внутренние буферы между объектами. В конце строки временный вектор, который был создан, удаляется, но у него есть кишки из старого вектора, а у старого вектора есть кишки из новой копии, которая является точным размером, который нам нужен.
Ответ 4
Идиоматическое решение состоит в том, чтобы поменять его на новый вектор.
vector<int>().swap(v);
Изменить: я неправильно понял вопрос. Приведенный выше код очистит вектор. OP хочет сохранить элементы нетронутыми, только сжимайте capacity()
до size()
.
Трудно сказать, сделает ли это код. Я сомневаюсь, что это портативное решение. Для gcc
вам нужно взглянуть на их конкретную реализацию vector
.
изменить. Итак, я заглянул в реализацию libstdС++. Кажется, что решение aJ действительно будет работать.
vector<int>(v).swap(v);
Смотрите источник, строка 232.
Ответ 5
Нет, вы не можете уменьшить емкость вектора без копирования. Тем не менее, вы можете контролировать, сколько нового роста распределения, проверяя емкость() и резерв вызовов() каждый раз, когда вы что-то вставляете. Поведение по умолчанию для std::vector заключается в том, чтобы увеличить его емкость в 2 раза каждый раз, когда требуется новая емкость. Вы можете развить его по своему магическому отношению:
template <typename T>
void myPushBack(std::vector<T>& vec, const T& val) {
if (vac.size() + 1 == vac.capacity()) {
vac.reserve(vac.size() * my_magic_ratio);
}
vec.push_back(val);
}
Если вы немного взломаны, вы всегда можете перейти в свой распределитель и сделать все, что вам нужно, чтобы восстановить неиспользуемую емкость.
Ответ 6
Я не говорю, что GCC не может иметь какой-либо метод для выполнения того, что вы хотите без копии, но было бы сложно реализовать (я думаю), потому что векторам нужно использовать объект Allocator
для выделения и освобождения память, а интерфейс для Allocator
не включает метод reallocate()
. Я не думаю, что это невозможно сделать, но это может быть сложно.
Ответ 7
Если вы беспокоитесь о накладных расходах вашего вектора, то, возможно, вам следует искать другую структуру данных. Вы упомянули, что как только ваш код будет завершен, инициализация вектора становится процессом только для чтения. Я бы посоветовал пойти с открытым массивом, который позволит программе определять свои возможности во время компиляции. Или, возможно, связанный список будет более подходящим для ваших нужд.
Лемме знаю, полностью ли я неправильно понял, к чему ты клонился.
-UBcse
Ответ 8
Старый поток, я знаю, но в случае, если кто-нибудь это просмотрит в будущем.. там shrink_to_fit() в С++ 11, но поскольку он является необязательным запросом, поведение будет зависеть от его реализации.
Смотрите: http://en.cppreference.com/w/cpp/container/vector/shrink_to_fit
Ответ 9
Получите книгу "Эффективный STL" Скотта Майерса. Он имеет полный элемент jus по уменьшению векторной емкости.