C++ Destructors
A destructor in C++ is a special member function of a class that is executed automatically when an object of the class is destroyed. The primary purpose of a destructor is to release any resources that were allocated to the object during its lifetime. This could include freeing dynamically allocated memory or closing files or network connections.
Just like constructors, destructors have the same name as the class, but they are preceded by a tilde (~
). Unlike constructors, destructors do not take any parameters and do not return any value.
A destructor is called when an object goes out of scope or is explicitly deleted. The destructor is responsible for performing the necessary cleanup, such as freeing memory or closing files, to prevent resource leaks. It is invoked automatically when the object is destroyed, and you cannot call it explicitly.
~
) before the name.delete
operator is used for dynamically allocated memory.The syntax for a destructor in C++ is straightforward. It follows the same name as the class, with a tilde (~
) in front of the class name.
class ClassName {
public:
// Destructor
~ClassName() {
// Cleanup code
}
};
A destructor is called automatically when:
delete
operator is used for dynamically allocated memory (in case of objects created with new
).Once the destructor is called, the object is destroyed, and its memory is reclaimed.
#include <iostream>
using namespace std;
class Person {
public:
string name;
// Constructor to initialize the object
Person(string n) {
name = n;
cout << "Constructor called for " << name << endl;
}
// Destructor to clean up resources
~Person() {
cout << "Destructor called for " << name << endl;
}
};
int main() {
// Creating a Person object
Person person1("Alice");
{
// Creating another Person object inside a block
Person person2("Bob");
} // person2 goes out of scope here, calling the destructor
return 0;
}
Output:
Constructor called for Alice
Constructor called for Bob
Destructor called for Bob
Destructor called for Alice
Explanation:
person1
and person2
are created. When person2
goes out of scope, its destructor is called.person1
goes out of scope, its destructor is also called.When an object is created using the new
keyword (dynamically allocated), the destructor is called when the object is explicitly deleted using the delete
operator.
#include <iostream>
using namespace std;
class Person {
public:
string *name;
// Constructor
Person(string n) {
name = new string(n); // Dynamically allocated memory
cout << "Constructor called: " << *name << endl;
}
// Destructor to clean up dynamically allocated memory
~Person() {
delete name; // Deallocating memory
cout << "Destructor called and memory freed." << endl;
}
};
int main() {
// Dynamically allocating memory for a Person object
Person *person = new Person("Charlie");
// Deleting the object to call the destructor
delete person;
return 0;
}
Output:
Constructor called: Charlie
Destructor called and memory freed.
Explanation:
Person
object is dynamically created using new
. This means memory is allocated for the object and for its name
string.name
using delete
.delete person;
line ensures that the destructor is called, and the memory is properly freed.Destructors are invoked in the following scenarios:
When an object goes out of scope:
When an object is deleted:
new
operator, the destructor is called when delete
is used.At the end of a program:
static
), destructors are called when the program ends.In case of inheritance, if a class is inherited from a base class, the base class destructor is automatically called before the derived class destructor when an object is destroyed. If the derived class has its own destructor, it will be called first.
If a derived class has a destructor, it is important to make the base class destructor virtual to ensure the correct destructor is called when a base class pointer is used to delete an object.
#include <iostream>
using namespace std;
class Base {
public:
// Base class constructor
Base() {
cout << "Base class constructor" << endl;
}
// Base class destructor
virtual ~Base() {
cout << "Base class destructor" << endl;
}
};
class Derived : public Base {
public:
// Derived class constructor
Derived() {
cout << "Derived class constructor" << endl;
}
// Derived class destructor
~Derived() {
cout << "Derived class destructor" << endl;
}
};
int main() {
// Creating an object of the derived class
Base *obj = new Derived();
// Deleting the object
delete obj;
return 0;
}
Output:
Base class constructor
Derived class constructor
Derived class destructor
Base class destructor
Explanation:
virtual
.virtual
was omitted from the base class destructor, only the base class destructor would have been called, leading to potential resource leaks.virtual
to ensure the correct destructor is called.delete
in destructors for local objects: Local objects that go out of scope do not require manual memory deallocation (it happens automatically).