vector <weight> decoy;
void clear_decoy() {
decoy.clear();
vector<weight> (decoy).swap(decoy);
}
В вышеупомянутом методе clear_decoy()
, что делает vector<weight> (decoy).swap(decoy);
средний?
Делает четкий метод decoy
или нет?Спасибо!
Он создает новый вектор объектов Weight
(который будет пустым) и меняет его местами с decoy
.
Причина этого в том, что по умолчанию std::vector
часто не уменьшает объем памяти, используемой вектором, а просто уничтожает все содержащиеся в нем объекты. Таким образом, в векторе остается место для хранения большего количества объектов без перераспределения в будущем.
Иногда, однако, вы хотите сократить емкость вектора. Замена на вновь созданный вектор (который живет до конца своей строки и поэтому уничтожается в ней) освобождает всю память, выделенную вектором.
Этот код представляет собой неудачную попытку использовать обычный трюк, чтобы гарантировать память, выделенная вектором, освобождается. Это может или не может на самом деле сделать это, в зависимости от того, выделяет ли конструктор копирования вектора память для соответствия размеру другого вектора или его емкости.
Чтобы надежно освободить память, используйте следующее:
void clear_decoy() {
vector<weight>().swap(decoy);
}
Это создает временный пустой вектор (с небольшой выделенной памятью или без нее), меняет его местами на приманку
, чтобы память теперь принадлежала временное, затем уничтожает временное, освобождая память.
clear
удаляет все записи из вектора, но не обязательно освобождает пространство. Эта идиома подкачки восстанавливает вектор без выделенного пространства.
Как упоминает 0A0D, эффект swap
заключается в обмене базовой управляемой памяти между двумя векторами. Но это требует немного большего объяснения.
Когда вы очищаете
вектор
, элементы удаляются из него, по крайней мере, с точки зрения программиста. size()
становится нулем, а capacity()
может измениться или не измениться. Но стандарт не гарантирует, что память, используемая вектором, действительно будет возвращена обратно в операционную систему. Так, если до clear()
в векторе было 1000 элементов, и каждый занимал 1000 байт памяти, то после clear()
будет вызван деструктор каждого элемента, но вектор может по-прежнему удерживать выделение 1 000 000 байт.
Иногда это нежелательно. Трюк "подмены", который вы отметили выше, имеет эффект обмена контролируемой памяти между двумя векторами. Следовательно, decoy
оказывается со сброшенной управляемой памятью.
Вот что происходит шаг за шагом:
элементы decoy
каждый стираются
.
Деструкторы элементов
вызываются, и размер() вектора
становится равным нулю. Фактическая память может
не может быть деаллоцирована. vector (decoy)
) и в него копируются элементы из decoy
. Поскольку decoy
был только что clear()
ed, никакие элементы не копируются во временный вектор. Однако, см. правку ниже. Вы не знаете, что управляемая память не подкачивается. decoy
меняются местами (.swap(decoy);
), в результате чего decoy
очищается, а его память передается временному. Это называется "трюк с подменой".
EDIT: Как упоминает Майк, оригинальный программист делает это неправильно. Временное не должно строиться на основе decoy
, оно просто должно строиться по умолчанию. Вы не знаете наверняка, что swap()
скопирует только элементы, а не управляемую память под ними.
Если ясно,
Все элементы вектора равны drop: вызываются их деструкторы, а затем они удаляются из векторный контейнер, оставив контейнер размером 0.
Swap просто меняет местами два вектора,
Swap content
Меняет содержимое вектора на содержание vec, которое является другим вектор того же типа. Размеры могут различаются.
После звонка этому участнику функции, элементы в этом контейнер - это те, которые были в vec перед звонком, а элементы vec - это те, которые были в этом. Все итераторы, ссылки и указатели остаются действительными для переставленных векторов.
Похоже, вы на самом деле ничего не меняете местами, а просто восстанавливаете распределение по умолчанию. Clear может освободить место, но иногда этого не происходит. Вы не только уменьшаете размер, но и уменьшаете пространство, выделяемое с помощью оператора подкачки.
Я никогда раньше не видел такой формы.
Я видел, что это написано так:
vector<weight>().swap(decoy);
Что означает «создать новый пустой вектор и заменить его существующим.
vector
Чтобы поймите это, разбейте его на части.
vector
создайте новый вектор (с его содержимым, скопированным из теперь пустой приманки). Новый вектор является автономным временным, поэтому давайте представим его имя это newvector
.
newVector.swap (decoy);
меняет местами новый вектор с помощью decopy.
(Обновлено согласно комментариям для исправления ошибки)