#include <iostream> using namespace std; class A { public: int a; A() { a=2; } ~A() { a=1; } }; int main() { A * aa = new A(); delete aa; if (aa) cout<< aa->a; else cout<<"123"; } 

I create a pointer to an instance of the class, call the constructor, the variable "a" contains the number 2. I call the destructor (in which this "a" should become equal to 1). At first I put check whether there is a pointer on a class copy. It turned out that not only does it exist after the destructor, the number 0 also lies in "a". Does it mean that zeros start to lie in the memory, but is it still occupied by the program? How to remove from memory the entire instance of the class? If I replace the reference to the class (in this case, "aa") with the missing one, then (logically) it will not release the memory, but will not allow me to manage this memory anymore via this link.

  • The standard misconception is that after delete , the pointer variable should be reset ... I wonder where its "legs grow from"? - Harry
  • @Harry I guess from ordinary human logic. Removing you want to delete. But that is not the question. Is an instance of a class really deleted from memory after delete or just all its memory cells take the value 0? - Gleb
  • It is precisely deleted, and that its cells take on some significance - so nothing is said about this in the standard ... - Harry
  • @Gleb: What does the phrase "put check if there is a pointer to an instance of a class". Why did you decide that this check checks whether a pointer exists? delete aa only deleted the object the pointer pointed to. delete aa does nothing with the pointer itself. Your pointer is a local variable. It will exist until the end of the block. - AnT
  • @AnT I decided that delete (as follows from the translation of the word) deletes it, and that not only the memory will be freed, but the pointer will point to NULL (after all, the delete is applicable to the pointer). In this case, the if from a pointer equal to NULL would return false. This is the essence of verification, it turned out that the index was not NULL. In lua, deleting the table and then checking the pointer to the table returned false, and I wondered how things were in the pros, why the address was not NULL, and how to free the memory then. - Gleb

4 answers 4

[basic.stc] / 4

This is a list of information that has been received. Indirection through an invalid pointer . Invalid pointer hasn

(emphasis mine)

After delete aa; , the aa pointer becomes invalid, and the behavior of if (aa) depends on the compiler.

More importantly, the next line, aa->a , causes undefined behavior, due to access through an invalid pointer.

Since the behavior is undefined, it makes no sense to argue why you see in console 0 or something else a little.


At first I put check whether there is a pointer on a class copy.

delete does not reset the pointer. So the check does not work.

not only does it exist after destructor

He does not exist". The object ceases to exist after calling on it destructor 1 .

That's just the language there is no way to check, indicates a pointer to an "existing" object, or not.

so also in the "a" is the number 0

a - also does not exist. Reading out of it is indefinite behavior.

It turns out that zeros start to lie in the memory, but is she still busy with the program? How to remove from memory the entire instance of the class?

What does "remove from memory" mean? Memory is a set of bytes. You can change the values ​​of the bytes in which the object was located to any other, and that's it. These bytes cannot be "deleted".


1 More precisely, a non-trivial destructor, but here it is not important.

  • Что значит "удалить из памяти"? meaning that memory is allocated for the needs of this program. In this case, I meant "free for other programs." - Gleb
  • Assign the nullptr element after the deletion, and the question will disappear by itself. - NewView
  • @Gleb Memory is given to the program and is released not for each object separately but in larger pieces. Example: coliru.stacked-crooked.com/a/2d888040e21f4088 - HolyBlackCat

After

 delete aa; 

the value of the pointer stored in the variable aa does not change .

And she points to a block of memory that has already been released, which can remain in the same state, be overwritten - in general, anything can happen to it (that’s Undefined Behaviour). In any case, you should not apply to it - it cannot lead to anything good.

  • the value of the pointer stored in the variable aa does not change. Or it can change for something else, but in any case it is not zero, but it can not change? .... - AR Hovsepyan
  • The delete operator is applied to the pointer. So what is the universal meaning of leaving this pointer to refer to a memory area that no longer belongs to a program? According to the logic of delete ptr; should call delete ptr; ptr = NULL; delete ptr; ptr = NULL; Personally, I do not see the point of leaving it if the memory really no longer belongs to the program. - Gleb
  • @Gleb The value of the pointer does not change, since it is passed to the operator-function delete by value. That is, the delete operator function deals with a copy of the value of the original pointer. - Vlad from Moscow
  • Just like this operator is used to delete an object whose address stores a pointer, And the pointer value may change as the program progresses, if the distributor decides to use this piece of memory ... - AR Hovsepyan
  • According to the logic of delete ptr; should call delete ptr; ptr = NULL; " According to your logic, delete ptr+2; (deleting the third element in the array, for example) should result in ptr+2 = NULL ? - Harry

The program has an undefined behavior, because after deleting a class object

 delete aa; 

pointer value aa becomes invalid. That is, the pointer does not indicate an existing "live" object in the program.

Keep in mind that when you call the operator-function delete or delete[] , the pointer value does not change. since the pointer is passed to the operator-function by value, that is, the operator-function deals with a copy of the value of the original pointer.

This means that checking in the if-предложении will give true

 if (aa) cout<< aa->a 

That is, aa is not a null-указатель ,

However, accessing a member of a no longer existing object.

  cout<< aa->a 

leads to indefinite behavior.

  • "... the value of the pointer does not change" - this is formally wrong. Such a pointer again acquires an indeterminate value, i.e. its value becomes unpredictable and possibly unstable. The statement that it "does not change" is too strong. Yes, delete cannot change it directly, but indirectly it “changes”. - AnT
  • @AnT In this context, the indeterminate value has the meaning that the pointer does not point to a real object, and not that its value has changed. That is, the status of the pointer value changes, not the value itself. - Vlad from Moscow
  • Not. This topic was much discussed in C and C ++. The practical aspect of this question is: if the value of aa was temporarily raised from memory to the register of the processor, then is it necessary to do a register spill after completing work with aa (that is, after delete aa; ) reset the last (indeterminate) register value back to memory? The answer is no need. It is for the sake of such optimization that the idea of ​​indeterminate value exists in C and C ++. Due to the fact that the last (register) value of aa can not be reset in memory, it can easily get the effect that the value of aa "changed" after delete aa; . - AnT

Let's increase the program a bit, then it will be clearer:

 struct A { int a; A(int k = 2) : a(k) {} ~A() { a=1; } }; 

program:

 A * aa = new A(); delete aa; if (aa) cout<< aa->a << '\t' << aa << endl; // else cout<<"123" << endl; A* bb = new A(1245); // может использоваться память содержащайся в аа а может и нет cout << bb << '\t' << bb->a << endl; // теперь хотим использовать и обьявленный b и адрес хранящийся в аа // размещаем в аа новый обьект bb = new(aa) A(); //теперь оба указателья содержат один и тот же адрес cout << aa << '\t' << bb << endl << aa->a <<'\t' << bb->a; 

The compiler does not know what the programmer wants to do with the allocated memory (or does not want to). Therefore, it is не нужно , as stated above, проверить, указывает указатель на "существующий" объект, или нет, не только потому что нет в языке такого способа. whether a проверить, указывает указатель на "существующий" объект, или нет, не только потому что нет в языке такого способа.