С++ удалить вектор, объекты, свободную память
Я полностью запутался в отношении удаления вещей в С++
Если я объявляю массив объектов, и если я использую функцию clear()
. Могу ли я быть уверенным, что память была выпущена?
Например:
tempObject obj1;
tempObject obj2;
vector<tempObject> tempVector;
tempVector.pushback(obj1);
tempVector.pushback(obj2);
Можно ли безопасно вызывать ясность, чтобы освободить всю память? Или мне нужно выполнить итерацию, чтобы удалить один за другим?
tempVector.clear();
Если этот сценарий изменен на указатель объектов, ответ будет таким же, как и выше?
vector<tempObject> *tempVector;
//push objects....
tempVector->clear();
Ответы
Ответ 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, чтобы инициализировать их, если требуется.