C ++ vector :: clear - PullRequest
       20

C ++ vector :: clear

23 голосов
/ 13 августа 2010
vector <weight> decoy;

void clear_decoy() {  

    decoy.clear();   

    vector<weight> (decoy).swap(decoy);  
}

В приведенном выше методе clear_decoy(), что означает vector<weight> (decoy).swap(decoy); , пожалуйста?

Метод очищает decoy или нет? Спасибо!

Ответы [ 6 ]

22 голосов
/ 13 августа 2010

Я никогда раньше не видел эту форму.

Я видел ее в виде:

vector<weight>().swap(decoy);

Что означает «создать новый пустой вектор и заменить его на существующий»..

vector<weight> (decoy).swap(decoy);

Чтобы понять это, разбейте на части.

vector<weight>(decoy) создайте новый вектор (его содержимое скопировано из теперь пустой ложки).Новый вектор является автономным временным, поэтому давайте представим, что его имя newvector.

newVector.swap(decoy); заменяет новый вектор на decopy.

(обновлено в комментариях, чтобы исправить ошибку)

20 голосов
/ 13 августа 2010

Создает новый вектор из Weight объектов (который будет пустым) и заменяет его на decoy.

Причина этого заключается в том, что по умолчанию std::vector<t>::clear на самом деле часто неуменьшить объем памяти, используемый вектором, он просто уничтожает все содержащиеся в нем объекты.Таким образом, в векторе будет место для хранения большего количества объектов без перераспределения в будущем.

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

10 голосов
/ 13 августа 2010

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

Для надежного освобождения памяти используйте следующее:

void clear_decoy() {  
    vector<weight>().swap(decoy);  
}

Это создает временный пустой вектор (с небольшим объемом памяти или без нее), заменяет его на decoy, так что память теперь принадлежит временному, а затем уничтожает временный, освобождая память.

6 голосов
/ 13 августа 2010

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

3 голосов
/ 13 августа 2010

Как упоминает 0A0D, эффект swap заключается в обмене базовой управляемой памятью между двумя векторами. Но это требует немного большего объяснения.

Когда вы clear a vector, элементы удаляются из него по крайней мере, насколько это касается программиста. size() становится равным нулю, а capacity() может изменяться или не изменяться. Но Стандарт не гарантирует, что используемая вектором память будет фактически возвращена операционной системе. Таким образом, если у вас было 1000 элементов в векторе до clear() и каждый занимал 1000 байтов памяти, после clear() вызывается деструктор каждого элемента, но вектор все еще может удерживать распределение в 1 000 000 байт.

Это иногда нежелательно. Вышеупомянутый «трюк обмена» имеет эффект обмена управляемой памятью между двумя векторами. Следовательно, decoy завершается управляемым сбросом памяти.

Вот что происходит шаг за шагом:

  1. decoy элементов каждый erased. Деструкторы элементов называется, а вектор size() становится ноль. Фактическая память может не быть освобожденным.
  2. В стеке создается новый вектор (vector<weight> (decoy)), и элементы из decoy копируются в него. Поскольку decoy было просто clear() ed, никакие элементы не копируются во временный вектор. Однако, см. Правку ниже. Вы не знаете, что контролируемая память не поменялась местами.
  3. Временный вектор и decoy память меняются местами (.swap(decoy);), в результате чего decoy очищается и его память переносится во временный.
  4. Временная копия падает со стека, в результате чего ее память освобождается.

Это называется " трюк со свопом ".

РЕДАКТИРОВАТЬ: Как упоминает Майк, оригинальный программист делает это неправильно. Временный не должен быть построен на основе decoy, он должен быть построен по умолчанию. Вы точно не знаете, что swap() будет копировать только элементы, а не контролируемую память под ними.

1 голос
/ 13 августа 2010

При очистке,

Все элементы вектора удаляются: вызываются их деструкторы, а затем они удаляются из контейнера вектора, оставляя контейнер с размером 0.

Поменять местами только два вектора,

Поменять содержимое

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

После вызова этой функции-члена элементы в этом контейнере - это те, которые были в vec до вызова, а элементы vec - те, которые были в этом.Все итераторы, ссылки и указатели остаются действительными для переставляемых векторов.

Кажется, вы ничего не меняете на самом деле и просто восстанавливаете распределение по умолчанию.Очистить можно освободить, но иногда нет.Вы не только уменьшаете размер, но и уменьшаете пространство, выделенное оператором swap.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...