Destructors
Objects that are not needed anymore have to be properly destroyed. That means that part of memory which was assigned to some object needs to be freed when that object is not needed anymore.
Mechanism that C++ offers for guaranteed destruction of an object is based on special class methods called destructors. If a class has a destructor, then whenever it is time for an object of that class to be destroyed destructor will be called automatically.
Destructor declaration
~class_name();
Destructor has ~, doesn’t have any parameters, has no return value and should be defined in public section of the class.
class C{
C(int a, int b){}//constructor
~C(){}//destructor
}
Like default and copy constructor, destructor should be explicitly defined also. Class has pointers as data members quite often so we need to deallocate the memory that the pointer points to, so we can prevent memory leak (default destructor doesn’t do it for us). Destructor is also the reason why these pointers need to be properly initialized, at least with null values (operator delete has no harmful effect when used on null pointer).
Class C{
int* array;
int len;
public:
C(int len){ array= new int[len];}
~C(){delete [] array; array=nullptr ;}
}
If an object that is being destroyed has class type data members with destructors, destructor body of that object is being executed first and then destructors of those data members. Data members are being destroyed in opposite way of their creation.
If a class doesn’t have explicitly defined destructor, then it is automatically generated with an empty body. That assures us that destructors of class type attributes that object contains will be called. That auto-generated destructor is not good for classes that have pointers as data members.
Destructors can be called explicitly. If we have a class C and an object c, then we could call it like C: :~C(), c.~C() and c ->~C() (if c is a pointer). We can also call it inside class methods with this->~C(). Explicit call of the destructor should be avoided since it works as a normal function and after it, the object will still exist. Instead, if we want to “empty” our object, it is better to make a function for it. In that case, destructor can use only that method in its body.
Class C{
int* array;
int b;
public:
//whatever...
void empty(){ delete [] a; a=nullptr ;b=0;}
~C(){empty();}
}
Table of contents
- Operator Overloading
- Class Inheritance
- Exceptions
- Namespaces
- Templates
- Standard Library
- Additional Problems