В чем разница между удалением указателя, установкой его на нуль и освобождением его.
delete ptr;
против.
ptr=NULL;
против.
free(ptr);
В чем разница между удалением указателя, установкой его на нуль и освобождением его.
delete ptr;
против.
ptr=NULL;
против.
free(ptr);
Ваш вопрос подсказывает, что вы пришли с языка, на котором есть сбор мусора. С++ не содержит сборку мусора.
Если вы указали указатель на NULL, это не приведет к возврату памяти в пул доступной памяти. Если никакие другие указатели не указывают на этот блок памяти, теперь у вас просто есть "осиротевший" блок памяти, который остается выделенным, но теперь недоступен - утечка. Утечки только приводят к сбою программы, если они строятся до точки, в которой памяти не выделяется.
Там также обратная ситуация, когда вы delete
блок памяти с помощью указателя, а затем попытаетесь получить доступ к этой памяти, как если бы она все еще была выделена. Это возможно, потому что вызов delete
на указатель не устанавливает указатель в NULL - он все же указывает на адрес ранее сохраненной памяти. Указатель на память, которая больше не выделяется, называется висящим указателем, и доступ к ней обычно вызывает странное поведение программы и сбои, поскольку ее содержимое, вероятно, не то, что вы ожидаете - эта часть памяти может иметь поскольку был перераспределен для некоторых других целей.
[EDIT] Как упоминает stinky472, другое различие между delete
и free()
заключается в том, что только первый вызов вызывает деструктор объекта. (Помните, что вы должны вызывать delete
для объекта, выделенного с помощью new
и free()
для памяти, выделенной с помощью malloc()
- их нельзя смешивать). В С++ всегда лучше использовать статическое распределение, если возможно, но если нет, то предпочитайте new
- malloc()
.
delete
предоставит выделенную память обратно в библиотеку времени выполнения С++. Вам всегда нужен соответствующий new
, который раньше выделял память в куче. NULL
- это нечто совершенно другое. "Заполнитель" означает, что он указывает на отсутствие адреса. В С++ NULL
- это MACRO, определенный как 0
. Поэтому, если не нравится MACROS, использование 0
напрямую также возможно. В С++ 0x nullptr
вводится и предпочтительнее.
Пример:
int* a; //declare pointer
a = NULL; //point 'a' to NULL to show that pointer is not yet initialized
a = new int; //reserve memory on the heap for int
//... do more stuff with 'a' and the memory it points to
delete a; //release memory
a = NULL; //(depending on your program), you now want to set the pointer back to
// 'NULL' to show, that a is not pointing to anything anymore
Хорошо, если вы создали объект динамически (с "новым" ), указатель указателя на любое значение не удаляет объект из памяти - и вы получаете утечку памяти.
Как и при любом обращении, при использовании указателей есть два объекта: referrer (указатель в вашем примере ptr
) и ссылочный объект (что он указывает на, *ptr
). Вам нужно научиться различать их.
Когда вы назначаете NULL
указателю, влияет только на указатель, объект, на который он ссылается, остается в покое. Если указатель был последним, указывающим на этот объект, вы потеряли последний указатель ссылки, указывающий на него, и, следовательно, больше не сможете его использовать. Однако в С++ это не означает, что объект будет удален. С++ не содержит сборку мусора. Таким образом, объект просочился.
Чтобы объекты удалялись, вам нужно удалить их вручную, передав их адрес (сохраненный в указателе) оператору delete
. Если вы это сделаете, будет затронут только объект, на который ссылается, указатель останется в покое. Он все равно может указывать на адрес, в котором объект находился в памяти, хотя он больше не используется. Это называется болтающимся указателем.
При создании объекта с использованием нового вам необходимо использовать delete, чтобы вернуть его обратно в систему. Затем память будет доступна для повторного использования другими пользователями.
int* a = new int;
delete a;
NULL - это только предопределенный макрос, которому может быть присвоен указатель, означающий, что он не указывает на что-либо.
int* a = new int;
a = NULL;
В приведенном выше случае после выделения хранилища для a вы назначаете ему NULL. Однако память, ранее выделенная для a, не была выпущена и не может быть повторно использована системой. Это то, что мы называем утечкой памяти.
int * ptr = null;
Вызов free(ptr)
ничего не сделает. Согласно стандарту, если заданный указатель равен нулю, никаких действий не происходит.
Использование delete p
также ничего не сделает. В стандарте С++ говорится, что никаких действий не произойдет, потому что он указывает на ничего и не доступен тип.