Удаление указателя в C++
контекст: я пытаюсь обернуть голову вокруг указателей, мы только что видели их пару недель назад в школе, и во время практики сегодня я столкнулся с глупым? проблема, это может быть очень просто для вас, но у меня мало опыта программирования.
Я видел довольно много вопросов в SO об удалении указателей, но все они, похоже, связаны с удалением класса, а не "простого" указателя (или независимо от того, какой правильный термин может быть), вот код, который я пытаюсь беги:
#include <iostream>;
using namespace std;
int main() {
int myVar,
*myPointer;
myVar = 8;
myPointer = &myVar;
cout << "delete-ing pointers " << endl;
cout << "Memory address: " << myPointer << endl;
// Seems I can't *just* delete it, as it triggers an error
delete myPointer;
cout << "myPointer: " << myPointer << endl;
// Error: a.out(14399) malloc: *** error for object 0x7fff61e537f4:
// pointer being freed was not allocated
// *** set a breakpoint in malloc_error_break to debug
// Abort trap: 6
// Using the new keyword befor deleting it works, but
// does it really frees up the space?
myPointer = new int;
delete myPointer;
cout << "myPointer: " << myPointer << endl;
// myPointer continues to store a memory address.
// Using NULL before deleting it, seems to work.
myPointer = NULL;
delete myPointer;
cout << "myPointer: " << myPointer << endl;
// myPointer returns 0.
}
Итак, мои вопросы:
- почему первый случай не работает? Кажется, самое простое использование для использования и удаления указателя? Ошибка говорит, что память не была выделена, но "cout" вернул адрес.
- во втором примере ошибка не запускается, но делает cout значения myPointer еще возвращает адрес памяти?
- действительно ли #3 работает? Кажется, работает для меня, указатель больше не хранение адреса-это правильный способ удаления указателя?
извините за длинный вопрос, хотел сделать это как можно более ясным, а также повторить, у меня мало опыта программирования, поэтому, если кто-то может ответить на это, используя термины непрофессионала, было бы очень признателен!
6 ответов
1 & 2
myVar = 8; //not dynamically allocated. Can't call delete on it.
myPointer = new int; //dynamically allocated, can call delete on it.
первая переменная была выделена на стеке. Вы можете вызвать delete только в памяти, выделенной динамически (в куче) с помощью new
оператора.
3.
myPointer = NULL;
delete myPointer;
выше сделал ничего. Вы ничего не освободили, так как указатель указывал на NULL.
Не следует делать следующее:
myPointer = new int;
myPointer = NULL; //leaked memory, no pointer to above int
delete myPointer; //no point at all
вы направили его на NULL, оставляя после себя утечку памяти (новый int, который вы выделили).
Вы должны освободить память, на которую указывали. Нет способа получить доступ к выделенному new int
больше, следовательно, утечка памяти.
правильно:
myPointer = new int;
delete myPointer; //freed memory
myPointer = NULL; //pointed dangling ptr to NULL
лучше:
если вы используете C++,не использовать сырые указатели. Использовать смарт-указатели вместо этого, который может справиться с этими вещами для вас с небольшим накладные расходы. В C++11 поставляется с несколько.
Я считаю, что вы не полностью понимаете, как работают указатели.
Когда у вас есть указатель, указывающий на некоторую память, вы должны понять три разные вещи:
- есть" то, на что указывает " указатель (память)
- этот адрес памяти
- не все указатели должны иметь их память удалена: вам нужно только удалить память, которая была динамически выделена (используется new
оператор).
представьте себе:
int *ptr = new int;
// ptr has the address of the memory.
// at this point, the actual memory doesn't have anything.
*ptr = 8;
// you're assigning the integer 8 into that memory.
delete ptr;
// you are only deleting the memory.
// at this point the pointer still has the same memory address (as you could
// notice from your 2nd test) but what inside that memory is gone!
когда вы сделал
ptr = NULL;
// you didn't delete the memory
// you're only saying that this pointer is now pointing to "nowhere".
// the memory that was pointed by this pointer is now lost.
C++ позволяет вам попробовать delete
указатель, который указывает на null
но на самом деле он ничего не делает, просто не дает никакой ошибки.
указатели похожи на обычные переменные в том, что вам не нужно, чтобы удалить их. Они удаляются из памяти в конце выполнения функций и / или в конце программы.
однако вы можете использовать указатели для выделения "блока" памяти, например, так:
int *some_integers = new int[20000]
это выделит пространство памяти для 20000 целых чисел. Полезно, потому что стек имеет ограниченный размер, и вы можете возиться с большой нагрузкой "ints" без переполнения стека ошибка.
всякий раз, когда вы вызываете new, вы должны затем "удалить" в конце вашей программы, потому что в противном случае вы получите утечку памяти, и некоторое выделенное пространство памяти никогда не будет возвращено для других программ для использования. Для этого:
delete [] some_integers;
надеюсь, что это поможет.
в C++ есть правило, для каждого новая есть удалить.
- почему первый случай не работает? Кажется, самое простое использование для использования и удаления указателя? Ошибка говорит, что память не была выделена, но "cout" вернул адрес.
new никогда не вызывается. Таким образом, адрес, который печатает cout, - это адрес местоположения памяти myVar или значение, назначенное myPointer в этом деле. Написав:
myPointer = &myVar;
вы говорите:
myPointer = адрес, где хранятся данные в myVar
- во втором примере ошибка не запускается, но выполнение cout значения myPointer по-прежнему возвращает адрес памяти?
возвращает адрес, который указывает на участок памяти, который был удален. Потому что сначала вы создаете указатель и назначьте его значение myPointer, во-вторых, удалите его, в-третьих, распечатайте его. Поэтому, если вы не присвоите myPointer другое значение, удаленный адрес останется.
- действительно ли #3 работает? Кажется, работает для меня, указатель больше не хранит адрес, это правильный способ удалить указатель?
NULL равно 0, вы удаляете 0, поэтому вы ничего не удаляете. И это логично, что он печатает 0, потому что вы сделали:
myPointer = NULL;
что равно:
myPointer = 0;
- вы пытаетесь удалить переменную в стеке. Вы не можете этого сделать
- удаление указателя фактически не уничтожает указатель, только занятая память возвращается в ОС. Вы можете получить к нему доступ, пока память не будет использоваться для другой переменной или иным образом манипулировать. Поэтому рекомендуется установить указатель на NULL (0) после удаления.
- удаление нулевого указателя ничего не удаляет.
int value, *ptr;
value = 8;
ptr = &value;
// ptr points to value, which lives on a stack frame.
// you are not responsible for managing its lifetime.
ptr = new int;
delete ptr;
// yes this is the normal way to manage the lifetime of
// dynamically allocated memory, you new'ed it, you delete it.
ptr = nullptr;
delete ptr;
// this is illogical, essentially you are saying delete nothing.