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

Должен ли я всегда вызывать vector clear() в конце функции?

У меня есть простая функция, которая использует вектор, подобный этому (псевдокод):

void someFunc(void) {

    std::vector<std::string> contentVector;

    // here are some operations on the vector

    // should I call the clear() here or this could be ommited ?
    contentVector.clear();

}

Должен ли я вызвать clear(), или это может быть пропущено?

4b9b3361

Ответ 1

Если мы посмотрим на cppreference.com для std::vector:: ~ vector в нем говорится:

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

так что вам не нужно вызывать clear.

Если мы хотим перейти в черновик стандарта, мы должны рассмотреть раздел 23.2.1 Общие требования к контейнерам, абзац 4, который гласит:

В таблицах 96 и 97 X обозначает класс контейнера, содержащий объекты типа T, a и b обозначают значения типа X, [...]

а затем посмотрите Table 96 — Container requirements, который имеет следующую запись выражения:

(&a)->~X()  

и следующее примечание:

note: деструктор применяется к каждому элементу a; вся память освобождается.

Обновить

Это RAII в действии, и как говорит Бьярне Страуструп в Почему 't С++ предоставляет "окончательную" конструкцию?:

Потому что С++ поддерживает альтернативу, которая почти всегда лучше: метод "сбора ресурсов - это инициализация" (раздел TС++ PL3, раздел 14.4). Основная идея заключается в представлении ресурса локальным объектом, так что локальный объект-деструктор освободит ресурс. Таким образом, программист не может забыть выпустить ресурс.

Ответ 2

Абсолютно не нужно этого делать. std::vector, и все остальные контейнеры автоматически уничтожают их элементы, когда они сами будут уничтожены. Это означает, что их деструкторы несут ответственность за это действие. Итак, не надо.

Красота этого заключается в том, что контейнеры, естественно, безопасны для защиты [1]:

void someFunc(void) {

    std::vector<std::string> contentVector;

    // here are some operations on the vector

    throw std::runtime_error("I just want to throw!");

    contentVector.clear();
}

Будет ли вызываться линия contentVector.clear();? Нет. Но вы все еще в безопасности, потому что гарантируется, что будет вызван деструктор contentVector.

Из vector [2]:

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


[1] Вам все равно нужно сделать свои элементы исключительными, хотя (правильно ли они освобождают свои ресурсы при вызове их деструкторов).

[2] См. комментарии ниже для некоторых мыслей о документах SGI STL.

Ответ 4

Так как я не думаю, что кто-то еще упомянул об этом, но если ваш вектор был

std::vector<std::string*> vector;

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

for (auto i : vector) {
  delete i;
}

Ответ 5

Вы можете опустить с помощью функции .clear(), потому что vector destructor запускается после того, как contentVector выходит из области видимости в '}'.

Отменяет память, в которой хранятся векторные данные.