Чтобы понять, что означает освобождение памяти, вы должны сначала понять, что означает выделение памяти.Далее следует упрощенное объяснение.
Существует память.Память - это большой кусок материала, к которому вы можете получить доступ.Но так как это глобально, вам нужно каким-то образом разделить его.Какой-то способ определить, кто может получить доступ к каким частям памяти.Одна из систем, которая управляет распределением памяти, называется «кучей».
Куча владеет некоторым количеством памяти (часть принадлежит стеку, а другая - статическим данным, но сейчас это не имеет значения),В начале вашей программы куча говорит, что у вас нет доступа к памяти, принадлежащей куче.
То, что делает new int
, в два раза.Во-первых, он обращается к системе кучи и говорит: «Я хочу кусок памяти, подходящий для хранения int
».Он возвращает указатель именно на это: часть кучи, в которую вы можете безопасно сохранить и получить ровно одно значение типа int
.
Теперь вы гордый владелецодной int
ценности памяти.Куча гарантирует , что до тех пор, пока соблюдаются ее правила, все, что вы там поместите, будет сохраняться до тех пор, пока вы явно не измените его.Это завет между вами и всемогущей кучей.
Другая вещь, которую new int
делает, инициализирует эту часть кучи значением int
.В этом случае он инициализируется по умолчанию, поскольку не было передано никакого значения (new int(5)
инициализировало бы его значением 5).
С этого момента вам по закону разрешено хранить ровно один int
вэтот кусок памяти.Вам разрешено восстановить int
, хранящиеся там.И вам разрешено сделать еще одну вещь: сообщить куче, что вы закончили использовать эту память.
Когда вы вызываете delete p
, происходят две вещи.Во-первых, p
деинициализирован.Опять же, потому что это int
, ничего не происходит.Если бы это был класс, его деструктор был бы назван.
Но после этого delete
выходит в кучу и говорит: «Эй, куча: помните этот указатель на int
, который вы мне дали? Iс этим покончено. "Система кучи может делать все, что захочет.Возможно, это очистит память, как это делают некоторые кучи в сборках отладки.Однако в сборках релиза память может не очищаться.
Конечно, причина, по которой куча может делать все, что ей нужно, заключается в том, что момент , когда вы удаляете этот указатель, вы вводите вновое соглашение с кучей.Ранее вы просили часть памяти для int
, и куча обязана.Ты владел этой памятью, и куча гарантировала, что она твоя столько, сколько ты хотел.Вещи, которые вы положили туда, останутся там.
После того, как вы повеселились, вы вернули его в кучу.И вот здесь вступает в силу контракт. Когда вы говорите delete p
, для любой объект p
, вы говорите следующее:
Я торжественно клянусь не трогать этоадрес памяти снова!
Теперь куча может вернуть вам этот адрес памяти, если вы снова вызовете new int
.Это может дать вам другой.Но у вас есть доступ только к памяти, выделенной кучей в течение времени между new
и delete
.
Учитывая это, что это значит?
delete p;
cout << *p << "\t" << p << "\n";
На языке C ++ это называется "неопределенным поведением".В спецификации C ++ есть много вещей, которые заявлены как «неопределенные».Когда вы запускаете неопределенное поведение , может произойти все что угодно! *p
может быть 0. *p
может быть значением, которым оно было раньше.Выполнение *p
может привести к сбою вашей программы.
Спецификация C ++ - это контракт между вами и вашим компилятором / компьютером.Он говорит, что вы можете сделать, и он говорит, как реагирует система.«Неопределенное поведение» - это то, что происходит, когда вы нарушаете контракт, когда вы делаете что-то, что спецификация C ++ говорит, что вы не должны этого делать.В этот момент все может произойти.
Когда вы позвонили delete p
, вы сказали системе, что вы закончили , используя p
.Используя его снова, вы лгали системе.И поэтому система больше не должна соблюдать какие-либо правила, такие как хранение значений, которые вы хотите сохранить.Или продолжать бежать.Или не порождение демонов из вашего носа.Или что угодно.
Вы нарушили правила.И вы должны страдать от последствий.
Так что нет, delete p
не является эквивалентом *p = 0
.Последнее просто означает «установить 0 в память, на которую указывает p
».Первый означает «я закончил использовать память, указанную p
, , и я не буду использовать ее снова , пока вы не скажете мне, что я могу».