Подтвердить что ты не робот

"Правильный" способ освободить объект std::vector

Первое решение:

std::vector<int> *vec = new std::vector<int>;
assert(vec != NULL);
// ...
delete vec;

альтернатива:

std::vector<int> v;
//...
vec.clear();
vec.swap(std::vector<int>(vec));

Второе решение - это трюк - какой "правильный" способ сделать это?

Обновление:

Я знаю, что деструктор будет вызван после его завершения, мне было интересно узнать о других методах.

4b9b3361

Ответ 1

Самый простой и надежный способ освободить вектор - объявить его в стеке и просто ничего не делать.

void Foo() {
  std::vector<int> v;
  ...
}

С++ гарантирует, что деструктор v будет вызываться при выполнении метода. Деструктор std::vector обеспечит освобождение выделенной памяти. Пока тип T vector<T> имеет правильную семантику освобождения С++, все будет хорошо.

Ответ 2

Самый простой способ освободить все хранилище в векторе без разрушения самого векторного объекта -

vec = std::vector<int>();

Ваш второй вариант будет иметь тот же эффект, но он прыгает через большее количество обручей в пути. Трюк "copy and swap" освобождает лишнюю емкость в векторе и может быть полезен, если он содержит некоторые данные, которые вы хотите сохранить. Если нет данных, тогда нет необходимости в копировании или замене.

Ответ 3

std::vector<int> vi;
/*push lots of stuff into the vector*/

// clean it up in C++03
// no need to clear() first
std::vector<int>().swap(vi);

// clean it up in C++0x
// not a one liner, but much more idiomatic
vi.clear();
vi.shrink_to_fit();

Ответ 4

Я согласен с Майком Сеймуром попробуйте это, тогда вы заметите, что последнее работает нормально

const int big_size = 10000;
vector<double> v( big_size );
cout << "Before clearing, the capacity of the vector is "
  << v.capacity() << " and its size is " << v.size();
v.clear();
cout << "\nAfter clearing, the capacity of the vector is "
  << v.capacity() << " and its size is " << v.size();
vector<double>().swap( v );

cout << "\nAfter swapping, the capacity of the vector is "
  << v.capacity() << " and its size is " << v.size();

vector<double> v1( big_size );
v1 = vector<double>();
cout << "\n After vector<double>();, the capacity of the vector is "
  << v1.capacity() << " and its size is " << v1.size();

Ответ 5

Не используйте функции выделения памяти, если вам это действительно нужно. Если вашему классу нужен вектор, всегда, просто введите std::vector. Нет необходимости делать выделение памяти здесь.

В тех случаях, когда вам нужен динамический вектор, выделение и удаление его, как в первом примере, на 100% правильное.

Во втором примере вызов std:: swap строго не нужен, потому что метод clear очистит вектор, делая его пустым. Одна из возможных проблем заключается в том, что нет гарантии, что вектор фактически освободит память, вернув ее в операционную систему (или во время выполнения). Вектор может содержать выделенную память на случай, если вы заполните вектор сразу после его очистки. Вызов std:: swap может быть трюком, чтобы "заставить" вектор освобождать свои внутренние данные, но нет никакой гарантии, что это действительно произойдет.

Ответ 6

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

Решения в порядке убывания желательности:

  • Исправьте код так, чтобы вектор с использованием кода был в нем собственный блок/функция/объект, чтобы он был уничтожен естественным образом.
  • Используйте трюк подкачки, так что вам не нужно беспокоиться о том, чтобы вектор был освобожден при любых обстоятельствах. Это время жизни будет привязано к объекту/функции, в которой вы находитесь.
  • новый/удалить вектор. Это освободит немного больше памяти, чем предыдущий, но также сложнее убедиться, что утечка памяти отсутствует.

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

Большее внимание - это облегчение написания правильного кода, и я считаю, что swap выигрывает при удалении там, но хуже, чем перемещение вектора где-то еще.

Ответ 7

Удалить освобождает память, затем память освобождается для следующего объекта, но вектор ушел.

Второй трюк освобождает лишнюю память, но оставляет вектор неповрежденным, но пустым.

Ответ 8

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

Ответ 9

Если вы просто позволите вектору выйти из сферы действия, он будет очищаться надлежащим образом без дополнительной работы. Если вектор является переменной-членом класса и вы хотите освободить его содержимое до того, как его владелец будет разрушен, тогда просто вызовите vec.clear().

Если вы хотите сохранить вектор, но освободите память, содержащую его содержимое, тогда vec.swap(std::vector<int>()); сделает это. Нет необходимости копировать временную конструкцию в оригинал, если vec не содержит элементов, которые вы хотите сохранить, и просто хотите уменьшить выделенную память до уровня, близкого к текущему размеру().

Ответ 10

Это не является допустимым сравнением, поскольку примеры относятся к различным типам объектов: динамической продолжительности и локальной продолжительности. Вы можете вызвать деструктор ИЛИ использовать трюк подкачки (aka shrink_to_fit) с помощью одного из них. Правильный способ зависит от того, нужен ли вам векторный объект для сохранения или нет.

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

Ответ 11

Я не уверен, почему ваш второй пример использует конструктор копирования для временного, а не для конструктора по умолчанию. Это спасет строку .clear() кода.

Вы можете сделать это общее для любого объекта, даже если это не контейнер. Я предполагаю, что std:: swap специализирован для вызова vector:: swap.

template<typename T>
void ResetToDefault(T & value)
{
    std::swap(T(), value);
}

std::vector<int> vec;  
//...  
ResetToDefault(vec);

Ответ 12

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

std::auto_ptr<std::vector<int> > vec(new std::vector<int>);

особенно полезно с кодом типа:

std::auto_ptr<std::vector<int> > vec(vectorFactoryFunction());