Destructor in C++: Complete Guide to Working, Syntax & Examples
May 26, 2026 6 Min Read 85 Views
(Last Updated)
Modern C++ programs constantly create and destroy objects while handling memory, files, sockets, threads, and other system resources. Without proper cleanup, applications can suffer from memory leaks, resource retention issues, and unstable performance over time. That is where destructors become important. A destructor in C++ automatically cleans up resources when an object is destroyed, helping developers manage object lifecycles more safely and efficiently.
Read this blog to understand what destructors are in C++, how they work, their syntax, types, examples, benefits, applications, and best practices for proper resource management.
Quick Answer:
A destructor in C++ is a special member function that is automatically called when an object is destroyed. It is mainly used to release resources such as memory, files, database connections, or network resources. A destructor has the same name as the class but starts with a tilde ~ and does not return any value.
Table of contents
- What Is a Destructor in C++?
- Properties of Destructors in C++
- Types of Destructors in C++ With Examples
- Default Destructor
- User-Defined Destructor
- Virtual Destructor
- Pure Virtual Destructor
- Functional Classifications Based on Object Lifetime
- Modern Destructor Definitions in C++11 and Later
- Benefits of Destructors in C++
- Enables Automatic Resource Cleanup Through RAII
- Ensures Correct Cleanup in Inheritance Hierarchies
- Reduces Risk of Resource Retention Bugs
- Improves Reliability in Long-Running Applications
- Destructor vs Constructor in C++
- Applications of Destructors in C++
- Best Practices for Destructors in C++
- Conclusion
- FAQs
- Can a destructor in C++ be overloaded?
- Why do we use virtual destructors in C++?
- When is a destructor automatically called in C++?
What Is a Destructor in C++?
A destructor in C++ is a special member function that automatically cleans up resources when an object is destroyed or goes out of scope. It releases dynamically allocated memory, file handles, sockets, and other resources acquired during an object’s lifetime. A destructor uses the class name prefixed with a tilde (~) and has no parameters or return type. It supports the Resource Acquisition Is Initialization (RAII) principle and is called automatically when scope ends or delete is used. In inheritance, destructors execute in reverse order, helping prevent memory leaks and ensuring proper resource management.
Properties of Destructors in C++
- Uses the Same Name as the Class With a Tilde (~)
A destructor always has the same name as its class prefixed with a tilde (~). For a class named Student, the destructor name becomes ~Student(). This naming convention allows the compiler to identify it as an object cleanup function.
- Has No Return Type
Destructors do not return any value, not even void. Their purpose is to perform cleanup operations rather than produce output, which is why specifying a return type is not allowed.
- Cannot Accept Parameters
A destructor cannot take arguments because object destruction should happen automatically without requiring additional input. Therefore, destructors cannot support parameter passing.
- Cannot Be Overloaded
Unlike constructors, a class can contain only one destructor. Since destructors cannot accept parameters, multiple destructor versions with different signatures are not allowed.
- Invoked Automatically by the Compiler
Destructors are called automatically when an object goes out of scope, when delete is used for dynamically allocated objects, or during program termination for static objects.
- Executes in Reverse Order of Construction
When multiple objects or inheritance hierarchies are involved, destructors execute in reverse order of object creation. Derived-class destructors run before base-class destructors to ensure correct resource cleanup.
- Supports Virtual Behavior in Polymorphism
Destructors can be declared virtual to enable proper cleanup in inheritance-based polymorphic systems. This ensures derived-class destructors execute correctly when deleting objects through base-class pointers.
- Can Be Compiler-Generated or User-Defined
If no destructor is explicitly written, the compiler automatically creates a default destructor. Developers can also define custom destructors to handle specialized cleanup operations.
- Can Be Declared as Pure Virtual
A destructor can be declared pure virtual using = 0, making the class abstract. However, unlike regular pure virtual functions, it still requires a definition outside the class.
Types of Destructors in C++ With Examples
Destructors in C++ can be classified based on compiler behavior, inheritance requirements, object lifetime, and modern C++ features. While all destructors perform object cleanup, their implementation and behavior vary depending on how objects are created, managed, and destroyed.
1. Default Destructor
A default destructor is automatically generated by the compiler when no destructor is explicitly defined in a class. This compiler-generated destructor is typically public and inline, and it automatically invokes destructors of all non-static data members and base classes in reverse order of construction. It is suitable for classes that do not manage dynamic memory or external resources.
#include <iostream>
using namespace std;
class Student {
public:
string name;
};
int main() {
Student s1;
return 0;
}
In this example, the compiler automatically creates a default destructor because none is defined by the programmer.
2. User-Defined Destructor
A user-defined destructor is explicitly written by the programmer to perform custom cleanup logic. It is commonly used when classes allocate memory using new, manage file streams, network sockets, database sessions, or other system resources. User-defined destructors help avoid memory leaks and provide precise resource deallocation.
#include <iostream>
using namespace std;
class Data {
private:
int* ptr;
public:
Data() {
ptr = new int(100);
}
~Data() {
delete ptr;
cout << "Memory released" << endl;
}
};
int main() {
Data d1;
return 0;
}
The destructor explicitly deallocates heap memory using delete.
3. Virtual Destructor
A virtual destructor is declared using the virtual keyword in a base class. It ensures that when a derived-class object is deleted through a base-class pointer, the derived-class destructor executes first, followed by the base destructor. This mechanism is essential in polymorphic systems to prevent incomplete cleanup and memory leaks.
#include <iostream>
using namespace std;
class Base {
public:
virtual ~Base() {
cout << "Base Destructor" << endl;
}
};
class Derived : public Base {
public:
~Derived() {
cout << "Derived Destructor" << endl;
}
};
int main() {
Base* obj = new Derived();
delete obj;
return 0;
}
Output:
Derived Destructor
Base Destructor
The derived destructor executes first, followed by the base destructor.
4. Pure Virtual Destructor
A pure virtual destructor is declared using virtual ~ClassName() = 0;, making the class abstract. Unlike other pure virtual functions, a pure virtual destructor must still provide a definition outside the class because the base portion of derived objects still requires destruction during object cleanup.
#include <iostream>
using namespace std;
class Shape {
public:
virtual ~Shape() = 0;
};
Shape::~Shape() {
cout << "Pure Virtual Destructor Defined" << endl;
}
class Circle : public Shape {
};
int main() {
Shape* obj = new Circle();
delete obj;
return 0;
}
Output:
Pure Virtual Destructor Defined
Even though the destructor is pure virtual, its definition is mandatory because the base class portion still requires destruction.
Functional Classifications Based on Object Lifetime
- Automatic Destructor
An automatic destructor executes when a stack-allocated object goes out of scope. Local variables inside functions commonly use automatic destruction, making cleanup happen without explicit programmer intervention.
- Dynamic Destructor
A dynamic destructor executes when the delete operator destroys an object allocated using new. This destruction process is essential for reclaiming heap memory and avoiding resource leaks.
- Static Destructor
A static destructor executes during program termination for objects with static storage duration, such as global variables and static class members. These destructors help release resources before application shutdown.
Modern Destructor Definitions in C++11 and Later
- Explicitly Defaulted Destructor
C++11 introduced explicitly defaulted destructors using ~ClassName() = default;. This allows developers to request compiler-generated destructor behavior while keeping destructor intent visible in code.
- Deleted Destructor
A deleted destructor uses ~ClassName() = delete; to prevent destruction operations. This advanced technique restricts object lifecycle behavior and can make stack-based object creation impossible in specific design scenarios.
Build strong programming foundations with HCL GUVI’s C++ Course and master core concepts like OOP, memory management, constructors, destructors, and problem-solving through structured learning. Learn through a 100% online, self-paced format, earn a globally recognised certification, get full lifetime access to all course content, and receive dedicated forum support to clear your doubts.
Benefits of Destructors in C++
1. Prevents Memory Leaks During Dynamic Allocation
Destructors automatically release dynamically allocated memory and object-owned resources when an object’s lifecycle ends. This becomes particularly important in applications using new and delete, where forgetting cleanup operations can gradually consume system memory and reduce application stability.
2. Enables Automatic Resource Cleanup Through RAII
Destructors support the Resource Acquisition Is Initialization (RAII) principle by binding resource management to object lifetime. Resources such as file streams, sockets, mutexes, and database connections are automatically released when objects leave scope, reducing manual cleanup complexity.
3. Ensures Correct Cleanup in Inheritance Hierarchies
In object-oriented systems with inheritance, destructors execute in reverse order of object construction. This guarantees that derived-class resources are released before base-class cleanup begins, preserving proper destruction order and preventing resource inconsistencies.
4. Reduces Risk of Resource Retention Bugs
Manual resource management often introduces issues such as forgotten file closures, unreleased handles, or dangling pointers. Destructors centralize cleanup logic in one location, reducing repetitive code and minimizing lifecycle-related bugs.
5. Improves Reliability in Long-Running Applications
Applications such as servers, game engines, operating systems, and backend services create and destroy thousands of objects continuously. Proper destructor implementation ensures resources are consistently reclaimed, helping maintain stable memory usage and long-term application performance.
Destructor vs Constructor in C++
Constructors and destructors are special member functions in C++ that manage an object’s lifecycle. A constructor initializes an object and allocates resources during creation, while a destructor cleans up and releases resources during destruction. Though both are called automatically, they serve opposite purposes and differ in syntax and behavior. Understanding their differences helps developers manage memory and resources efficiently.
| Parameter | Constructor | Destructor |
| Purpose | Initializes an object | Destroys an object |
| Name | Same as class name | Same as class name with ~ |
| Parameters | Can have parameters | Cannot have parameters |
| Overloading | Can be overloaded | Cannot be overloaded |
| Call time | Called when object is created | Called when object is destroyed |
| Return type | No return type | No return type |
Applications of Destructors in C++
- Deallocating Nodes in Linked List and Tree Implementations
Custom data structures such as linked lists, binary trees, and graphs often allocate nodes dynamically using new. Destructors recursively release node memory when the structure is destroyed, preventing orphaned memory blocks and leaks.
- Automatically Closing fstream Objects in File Processing Systems
Applications that process logs, reports, CSV files, or text documents use file stream objects such as ifstream, ofstream, and fstream. Destructors automatically close open file handles when objects go out of scope, ensuring proper file resource cleanup.
- Releasing Database Session Objects in Backend Applications
Enterprise applications using database connectors create objects for queries and active sessions. Destructors help terminate these sessions and release connection resources after execution to avoid unnecessary database resource usage.
- Cleaning Socket Connections in Client-Server Applications
Network applications create TCP or UDP socket objects for communication. Destructors close socket connections after data transfer ends, preventing socket leaks and reducing unnecessary resource consumption in long-running systems.
- Releasing Mutex Locks and Thread Resources in Multithreaded Programs
Concurrent applications use mutexes, thread locks, and synchronization objects to control shared resources. Destructors automatically release these resources when execution ends, helping prevent deadlocks and resource retention issues.
- Logging and Debugging Object Destruction Events
Destructors are often used during debugging to track object lifecycles and cleanup behavior. Developers add log statements inside destructors to monitor object destruction, identify memory-related issues, and verify that dynamically allocated resources are released correctly.
Best Practices for Destructors in C++
- Use Smart Pointers Instead of Manual delete: Prefer std::unique_ptr and std::shared_ptr over raw pointers so memory cleanup happens automatically and the destructor does not need complex manual deallocation logic.
- Declare Base Class Destructors as virtual: If a class is intended for inheritance, make the destructor virtual to ensure derived class destructors execute correctly when deleting objects through base-class pointers.
- Avoid Throwing Exceptions Inside Destructors: Destructors should never throw exceptions because exceptions during object destruction can trigger std::terminate() and abruptly stop program execution.
- Release Only Resources Owned by the Object: A destructor should clean up only the memory, file handles, sockets, or resources directly owned by that object to avoid accidental deletion and undefined behaviour.
- Keep Destructor Logic Lightweight and Predictable: Avoid heavy computations, network calls, or complex business logic inside destructors because object cleanup should remain fast and focused on resource release only.
Conclusion
Destructors in C++ play an important role in keeping programs clean, efficient, and reliable. They automatically release memory, close files, terminate connections, and clean up resources when objects are destroyed, reducing the risk of memory leaks and resource-related issues. Whether you are working with simple classes, dynamic memory allocation, inheritance, or polymorphism, understanding destructors helps you build safer and more maintainable C++ applications. Mastering destructors is an important step toward writing efficient object-oriented and resource-friendly C++ code.
FAQs
Can a destructor in C++ be overloaded?
No. A class can have only one destructor because destructors cannot accept parameters, which prevents multiple destructor signatures.
Why do we use virtual destructors in C++?
Virtual destructors ensure that derived-class destructors execute correctly when objects are deleted using base-class pointers, preventing incomplete cleanup and memory leaks.
When is a destructor automatically called in C++?
A destructor is automatically called when an object goes out of scope, when delete is used for dynamically allocated objects, or during program termination for static objects.



Did you enjoy this article?