Контекст: Я пытаюсь осмыслить указатели, мы видели их всего пару недель назад в школе, а сегодня, тренируясь, я наткнулся на глупца? проблема, это может быть очень просто для вас, но у меня практически нет опыта программирования.
Я видел довольно много вопросов в 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 действительно работает? Мне кажется, работает, указатель больше не хранит адрес, это правильный способ удалить указатель?
Извините за длинный вопрос, хотел прояснить это как можно более ясно, также повторяю, у меня мало опыта программирования, поэтому, если бы кто-то мог ответить на этот вопрос, используя условия непрофессионала, был бы очень признателен!
c++
pointers
delete-operator
леопик
источник
источник
delete
то, что тыnew
. Также не требуется, чтобы указатель устанавливал значение NULL после его удаления. Если вам нужна безопасность, используйте интеллектуальные указатели, которые освобождают для вас память и выдают ошибки, когда вы пытаетесь получить к ним доступ, когда они чего-то не содержат.reset
и это освобождает старое. Чтобы освободить его без замены, звонитеrelease
. Когда он выходит за пределы области видимости, он уничтожается и может освободить память в зависимости от ее типа.std::unique_ptr
предназначен только для одного владельца.std::shared_ptr
освобождает его, когда последний владелец перестает владеть ресурсом. Они также безопасны в исключительных случаях. Если вы выделяете ресурс одним, а затем возникает исключение, ресурс будет правильно освобожден.Ответы:
1 и 2
myVar = 8; //not dynamically allocated. Can't call delete on it. myPointer = new int; //dynamically allocated, can call delete on it.
Первая переменная была размещена в стеке. Вы можете вызвать удаление только для динамически выделенной памяти (в куче) с помощью
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 есть несколько .
источник
delete myPointer
освобождает*myPointer
. Это правильно. НоmyPointer
продолжает указывать на ячейку памяти, которая была освобождена и не должна использоваться, поскольку это UB. Он будет недоступен после окончания области видимости только в том случае, если изначально это была локальная переменная.new
каждый день. (Я дрянной!)NULL
мы не сможем использовать его позже.Я считаю, что вы не совсем понимаете, как работают указатели.
Когда у вас есть указатель, указывающий на некоторую память, вы должны понимать три разные вещи:
- есть то, что указывает указатель (память)
- этот адрес памяти
- не все указатели нуждаются в удалении своей памяти: вы только необходимо удалить динамически выделенную память (используемый
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 целых чисел. Полезно, потому что стек имеет ограниченный размер, и вы можете возиться с большой загрузкой целых чисел без ошибки переполнения стека.
Всякий раз, когда вы вызываете new, вы должны затем «удалить» в конце вашей программы, потому что в противном случае вы получите утечку памяти, и некоторое выделенное пространство памяти никогда не будет возвращено для использования другими программами. Сделать это:
delete [] some_integers;
Надеюсь, это поможет.
источник
новый никогда не называется. Таким образом, адрес, который выводит cout, является адресом ячейки памяти myVar или значением, присвоенным myPointer в данном случае. Написав:
ты говоришь:
Он возвращает адрес, указывающий на удаленную ячейку памяти. Потому что сначала вы создаете указатель и присваиваете его значение myPointer, затем удаляете его, а затем распечатываете. Поэтому, если вы не присвоите myPointer другое значение, удаленный адрес останется.
NULL равно 0, вы удаляете 0, поэтому ничего не удаляете. И логично, что он печатает 0, потому что вы сделали:
myPointer = NULL;
что равно:
myPointer = 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.
источник