What is the dynamics of a C ++ delete expression?

This is just for the sake of curiosity, because I did not use new and delete in C ++, with the exception of the most basic applications.

I know delete frees memory. I am wondering how it handles more complex cases?

For example, if I have a custom class like this:

 class MyClass { public: MyClass(); ~MyClass() { delete [] intArray; } //public members here private: int* intArray; }; 

Assuming the class somehow allocates memory for the intArray , and then release it in the destructor. What if I used the class as follows: MyClass* myClass = new MyClass(); and later released it with delete myclass;

How do delete handle freeing all memory? Is the class destructor called first to release all the memory allocated by the class (i.e. int* intArray ) and then free the memory allocated for the class?

What if I had a class:

 class MyClass { public: MyClass(); ~MyClass() { delete anotherMyClass; } //public members here private: MyClass* anotherMyClass; }; 

Assuming anotherMyClass not allocated by a constructor that would quickly use memory, what if there was a MyClasses chain attached to each other, like a linked list? Will the delete operation in the destructor work in this case? Will every anotherMyClass recursively released when the destructor is called?

Are there any specific weird tricks or caveats with the new and delete operators that you know about?

+4
source share
2 answers

By pointing the pointer ( p ) to a dynamically allocated object, delete performs two functions:

  • It calls the dynamically allocated object's destructor. Note that when ~MyClass() completes, destructors are called for any member variables of the class.
  • It frees the memory occupied by the dynamically allocated object.

It does not look for member variables of the object for other pointers; he does not free another memory and does nothing.

If you need to free the memory pointed to by intArray , you need to delete in the MyClass destructor.

However, in almost all C ++ code, you do not need to worry about this. You should use smart pointers such as shared_ptr , unique_ptr , auto_ptr and scoped_ptr to automatically control dynamically allocated objects. Manual resource management is difficult at best and should be avoided when possible.

This is part of a broader idiom related to the area of ​​resource management (SBRM, also called resource initialization, or RAII). This is by far the most important design pattern to understand and use everywhere in your C ++ code.

If in your class you specified this instead:

 boost::scoped_ptr<int> intArray; 

then when the scoped_ptr<int> object is destroyed, it will free the pointer that it holds. Then you do not need to do any work to manually destroy the object.

In well-written, modern C ++ code, you rarely need to manually use delete . Smart pointers and other SBRM containers should be used to manage any type of resource that needs to be cleared, including dynamically allocated objects.


In your second example, given a linked list that looks like this:

 x -> y -> z -> 0 

you will have an order of operations that looks like this:

 delete x; x.~MyClass(); delete y; y.~MyClass(); delete z; z.~MyClass(); delete 0; [free memory occupied by z] [free memory occupied by y] [free memory occupied by x] 

Items in the linked list will be destroyed in reverse order.

+10
source
 delete intArray; 

I assume that intArray points to the first element of an int array? In this case, delete intArray gives undefined behavior. If you select through new[] , you must be freed through delete[] .

 delete[] intArray; 

Yes, I know, delete intArray can show to work perfectly on certain systems with certain versions of the compiler with certain compiler options - or it may not be so. This is undefined behavior for ya.

In addition, you must follow Rule of Three . Defining your own destructor, but using an implicit copy constructor and copy assignment operator is a recipe for disaster.

+1
source

All Articles