“Правильный” способ освободить станд.:: векторный объект

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

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

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

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

Что-то вроде приема второго решения---, что "правильный" путь состоит в том, чтобы сделать это?

Обновление:

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

34
задан Jacob 16 June 2010 в 15:15
поделиться

11 ответов

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

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

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

37
ответ дан 27 November 2019 в 16:36
поделиться

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

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

. Второй вариант будет иметь такой же эффект, но он перескакивает через большее количество обручей на способ. Уловка «копировать и переставлять» освобождает любую дополнительную емкость в векторе и может быть полезна, если он содержит некоторые данные, которые вы хотите сохранить. Если данных нет, то в копировании или подкачке нет необходимости.

15
ответ дан 27 November 2019 в 16:36
поделиться
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();
13
ответ дан 27 November 2019 в 16:36
поделиться

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

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

0
ответ дан 27 November 2019 в 16:36
поделиться

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

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

особенно полезно с кодом вроде:

std::auto_ptr<std::vector<int> > vec(vectorFactoryFunction());
0
ответ дан 27 November 2019 в 16:36
поделиться

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

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

0
ответ дан 27 November 2019 в 16:36
поделиться

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

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

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

std::vector<int> vec;  
//...  
ResetToDefault(vec);
0
ответ дан 27 November 2019 в 16:36
поделиться

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

0
ответ дан 27 November 2019 в 16:36
поделиться

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

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

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

1
ответ дан 27 November 2019 в 16:36
поделиться

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

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

0
ответ дан 27 November 2019 в 16:36
поделиться

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

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

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

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

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

1
ответ дан 27 November 2019 в 16:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: