c++: выделение места под контейнер

150
24 апреля 2019, 03:00

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

std::vector<int> storage;
storage.reserve(10000);

а что происходит, когда я вычищаю элементы из контейнера?

storage.clear();

Нужно ли мне опять зарезервировать объем или можно ли сделать такой clear(), чтобы осталась зарезервированная память

Answer 1

Функция clear не освобождает зарезервированную память. Чтобы она освободилась, нужно после clear вызвать shrink_to_fit.

Answer 2

Согласно документации по методу std::vector::clear() (вольный перевод):

Изменение фактического размера блока памяти не гарантируется, а потому отсутствует и гарантия изменения вместимости вектора. Для принудительного освобождения памяти необходимо использовать swap:

vector<T>().swap(x);   // высвобождаем память из-под x

A reallocation is not guaranteed to happen, and the vector capacity is not guaranteed to change due to calling this function. A typical alternative that forces a reallocation is to use swap:

vector<T>().swap(x);   // clear x reallocating 

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

Так что можно спокойно закладываться на то, что память повторно резервировать не надо.

Answer 3

Да, нужно повторно вызывать reserve. После очистки с помощью clear вектор формально считается пустым и вы не должны делать предположений о том что фактически сделал вектор с памятью. Так как стандарт ничего такого не требует и не обещает, то есть вектор может освободить всю память, ее часть или ничего не освобождать. Ничего страшного не произойдет если память не освободится, а вы повторно вызвали reserve. С другой стороны если память освободится, ваш повторный вызов reserve сделает то же что и первый - зарезервирует нужное количество памяти.

Answer 4

Т.е. из всего вышесказанного все таки выходит, что если работа с контейнером идет постоянно, то можно не особо заморачиваться после вычищения контейнера с резервированием памяти, поскольку старая не отдается системе и может быть использована повторно?

Будет тот же эффект, как будто я каждый раз резервирую память, т.е. при операциях добавления элемента лишнее время на выделение памяти под элемент тратиться не будет.

READ ALSO
Как &ldquo;победить&rdquo; инкапсуляцию

Как “победить” инкапсуляцию

Обычный пример с юнитом

130
Как индексировать сохраняемый файл Qimage

Как индексировать сохраняемый файл Qimage

Я нарезаю картинку в цикле и сохраняю ее таким способом

182
Как передать значение из реестра

Как передать значение из реестра

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

164
Как узнать, что окно открыто?

Как узнать, что окно открыто?

Какой метод отвечает за проверку открытия окна?

153