Destructors (C++ only)
Destructors are usually used to deallocate memory and do other cleanup for a class object and its class members when the object is destroyed. A destructor is called for a class object when that object passes out of scope or is explicitly deleted.
~
(tilde). For example: class X {
public:
// Constructor for class X
X();
// Destructor for class X
~X();
};
A destructor takes no arguments and has no return type. Its address
cannot be taken. Destructors cannot be declared const
, volatile
, const
volatile
or static
. A destructor can be
declared virtual
or pure virtual
.
If no user-defined destructor exists for a class and one is needed, the compiler implicitly declares a destructor. This implicitly declared destructor is an inline public member of its class.
A
has an
implicitly declared destructor. The following is equivalent to the
function the compiler would implicitly define for A
:
A::~A() { }
The compiler first implicitly defines the implicitly declared or explicitly defaulteddestructors of the base classes and
nonstatic data members of a class A
before defining the implicitly declared or explicitly defaulted destructor of
A
.
A destructor of a class A
is trivial if
all the following are true:
- It is implicitly defined or or explicitly defaulted
- All the direct base classes of
A
have trivial destructors - The classes of all the nonstatic data members of
A
have trivial destructors
If any of the above are false, then the destructor is nontrivial.
A union member cannot be of a class type that has a nontrivial destructor.
Class members that are class types can have their own destructors.
Both base and derived classes can have destructors, although destructors
are not inherited. If a base class A
or a member
of A
has a destructor, and a class derived from A
does
not declare a destructor, a default destructor is generated.
The default destructor calls the destructors of the base class and members of the derived class.
The destructors of base classes and members are called in the reverse order of the completion of their constructor:
- The destructor for a class object is called before destructors for members and bases are called.
- Destructors for nonstatic members are called before destructors for base classes are called.
- Destructors for nonvirtual base classes are called before destructors for virtual base classes are called.
When an exception is thrown for a class object with a destructor, the destructor for the temporary object thrown is not called until control passes out of the catch block.
Destructors are implicitly called when an automatic object (a local
object that has been declared auto
or register
,
or not declared as static
or extern
)
or temporary object passes out of scope. They are implicitly called
at program termination for constructed external and static objects.
Destructors are invoked when you use the delete
operator
for objects created with the new
operator.
#include <string>
class Y {
private:
char * string;
int number;
public:
// Constructor
Y(const char*, int);
// Destructor
~Y() { delete[] string; }
};
// Define class Y constructor
Y::Y(const char* n, int a) {
string = strcpy(new char[strlen(n) + 1 ], n);
number = a;
}
int main () {
// Create and initialize
// object of class Y
Y yobj = Y("somestring", 10);
// ...
// Destructor ~Y is called before
// control returns from main()
}
new
operator, you can explicitly
call the object's destructor. The following example demonstrates this:
#include <new>
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A::A()" << endl; }
~A() { cout << "A::~A()" << endl; }
};
int main () {
char* p = new char[sizeof(A)];
A* ap = new (p) A;
ap->A::~A();
delete [] p;
}
The statement A* ap = new (p) A
dynamically creates
a new object of type A
not in the free store but
in the memory allocated by p
. The statement delete
[] p
will delete the storage allocated by p
,
but the runtime will still believe that the object pointed to by ap
still
exists until you explicitly call the destructor of A
(with
the statement ap->A::~A()
).
Note: You can declare destructors as explicitly defaulted functions or deleted functions. For more information, see Explicitly defaulted functions (C++11) and Deleted functions (C++11).