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

Delete vs NULL vs free в С++

В чем разница между удалением указателя, установкой его на нуль и освобождением его.

delete ptr;

против.

ptr=NULL;

против.

free(ptr);
4b9b3361

Ответ 1

Ваш вопрос подсказывает, что вы пришли с языка, на котором есть сбор мусора. С++ не содержит сборку мусора.

Если вы указали указатель на NULL, это не приведет к возврату памяти в пул доступной памяти. Если никакие другие указатели не указывают на этот блок памяти, теперь у вас просто есть "осиротевший" блок памяти, который остается выделенным, но теперь недоступен - утечка. Утечки только приводят к сбою программы, если они строятся до точки, в которой памяти не выделяется.

Там также обратная ситуация, когда вы delete блок памяти с помощью указателя, а затем попытаетесь получить доступ к этой памяти, как если бы она все еще была выделена. Это возможно, потому что вызов delete на указатель не устанавливает указатель в NULL - он все же указывает на адрес ранее сохраненной памяти. Указатель на память, которая больше не выделяется, называется висящим указателем, и доступ к ней обычно вызывает странное поведение программы и сбои, поскольку ее содержимое, вероятно, не то, что вы ожидаете - эта часть памяти может иметь поскольку был перераспределен для некоторых других целей.

[EDIT] Как упоминает stinky472, другое различие между delete и free() заключается в том, что только первый вызов вызывает деструктор объекта. (Помните, что вы должны вызывать delete для объекта, выделенного с помощью new и free() для памяти, выделенной с помощью malloc() - их нельзя смешивать). В С++ всегда лучше использовать статическое распределение, если возможно, но если нет, то предпочитайте new - malloc().

Ответ 2

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

Ответ 3

Хорошо, если вы создали объект динамически (с "новым" ), указатель указателя на любое значение не удаляет объект из памяти - и вы получаете утечку памяти.

Ответ 4

Как и при любом обращении, при использовании указателей есть два объекта: referrer (указатель в вашем примере ptr) и ссылочный объект (что он указывает на, *ptr). Вам нужно научиться различать их.

Когда вы назначаете NULL указателю, влияет только на указатель, объект, на который он ссылается, остается в покое. Если указатель был последним, указывающим на этот объект, вы потеряли последний указатель ссылки, указывающий на него, и, следовательно, больше не сможете его использовать. Однако в С++ это не означает, что объект будет удален. С++ не содержит сборку мусора. Таким образом, объект просочился.

Чтобы объекты удалялись, вам нужно удалить их вручную, передав их адрес (сохраненный в указателе) оператору delete. Если вы это сделаете, будет затронут только объект, на который ссылается, указатель останется в покое. Он все равно может указывать на адрес, в котором объект находился в памяти, хотя он больше не используется. Это называется болтающимся указателем.

Ответ 5

При создании объекта с использованием нового вам необходимо использовать delete, чтобы вернуть его обратно в систему. Затем память будет доступна для повторного использования другими пользователями.


int* a = new int;
delete a;

NULL - это только предопределенный макрос, которому может быть присвоен указатель, означающий, что он не указывает на что-либо.


int* a = new int;
a = NULL;

В приведенном выше случае после выделения хранилища для a вы назначаете ему NULL. Однако память, ранее выделенная для a, не была выпущена и не может быть повторно использована системой. Это то, что мы называем утечкой памяти.

Ответ 6

int * ptr = null;

Вызов free(ptr) ничего не сделает. Согласно стандарту, если заданный указатель равен нулю, никаких действий не происходит.

Использование delete p также ничего не сделает. В стандарте С++ говорится, что никаких действий не произойдет, потому что он указывает на ничего и не доступен тип.