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

С++ удалить вектор, объекты, свободную память

Я полностью запутался в отношении удаления вещей в С++ Если я объявляю массив объектов, и если я использую функцию clear(). Могу ли я быть уверенным, что память была выпущена?

Например:

tempObject obj1;
tempObject obj2;
vector<tempObject> tempVector;

tempVector.pushback(obj1);
tempVector.pushback(obj2);

Можно ли безопасно вызывать ясность, чтобы освободить всю память? Или мне нужно выполнить итерацию, чтобы удалить один за другим?

tempVector.clear();

Если этот сценарий изменен на указатель объектов, ответ будет таким же, как и выше?

vector<tempObject> *tempVector;
//push objects....
tempVector->clear();
4b9b3361

Ответ 1

Вы можете вызвать clear, и это уничтожит все объекты, но это не освободит память. Прохождение через отдельные элементы также не поможет (какое действие вы бы предложили предпринять для объектов?) Что вы можете сделать, так это:

vector<tempObject>().swap(tempVector);

Это создаст пустой вектор без выделенной памяти и заменит его на tempVector, эффективно освободив память.

С++ 11 также имеет функцию shrink_to_fit, которую вы могли бы вызвать после вызова clear(), и теоретически она уменьшила бы емкость, соответствующую размеру (который теперь равен 0). Это, однако, необязательный запрос, и ваша реализация может игнорировать его.

Ответ 2

Здесь есть две отдельные вещи:

  • срок службы объекта
  • продолжительность хранения

Например:

{
    vector<MyObject> v;
    // do some stuff, push some objects onto v
    v.clear(); // 1
    // maybe do some more stuff
} // 2

В 1 вы очищаете v: это уничтожает все объекты, которые он хранит. Каждый из них получает свой деструктор, если вы его написали, и все, что принадлежит этому MyObject, теперь выпущено. Однако вектор v имеет право хранить необработанное хранилище на случай, если вы захотите его позже.

Если вы решили вставить в него еще несколько вещей между 1 и 2, это экономит время, поскольку оно может повторно использовать старую память.

В 2 вектор v выходит за рамки: любые объекты, которые вы вставляете в него с 1, будут уничтожены (как если бы вы явно вызвали очистку снова), но теперь базовое хранилище также (v больше не будет использоваться для повторного использования).


Если я изменил пример, поэтому v станет указателем, вам нужно явно удалить его, поскольку указатель, выходящий из области видимости в 2, не сделает этого для вас. Лучше использовать в этом случае что-то вроде std::unique_ptr, но если вы этого не сделаете, и v просочится, то также будет утечка выделенного хранилища. Как и выше, вам необходимо убедиться, что v удален, а вызов clear недостаточен.

Ответ 3

vector::clear() не освобождает память, выделенную вектором для хранения объектов; он вызывает деструкторы для объектов, которые он держит.

Например, если вектор использует массив в качестве хранилища резервных копий и в настоящее время содержит 10 элементов, то вызов clear() вызовет деструктор каждого объекта в массиве, но массив подстановки не будет освобожден, поэтому существует все еще sizeof(T) * 10 байтов, выделенных для вектора (по крайней мере). size() будет 0, но size() возвращает количество элементов в векторе, не обязательно размер хранилища резервных копий.

Что касается вашего второго вопроса, все, что вы выделяете с помощью new, вы должны освободить с помощью delete. По этой причине вы обычно не поддерживаете указатель на вектор. Существует редко (если вообще когда-либо) хорошая причина для этого, и вы предотвращаете очистку вектора, когда он покидает область действия. Однако вызов clear() будет действовать одинаково, независимо от того, как он был выделен.

Ответ 4

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

my_arr.resize()

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