Apply Now Apply Now Apply Now
header_logo
Post thumbnail
PROGRAMMING LANGUAGES

Destructor in C++: Complete Guide to Working, Syntax & Examples

By Vaishali

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


  1. What Is a Destructor in C++?
  2. Properties of Destructors in C++
  3. Types of Destructors in C++ With Examples
    • Default Destructor
    • User-Defined Destructor
    • Virtual Destructor
    • Pure Virtual Destructor
  4. Functional Classifications Based on Object Lifetime
  5. Modern Destructor Definitions in C++11 and Later
  6. 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
  7. Destructor vs Constructor in C++
  8. Applications of Destructors in C++
  9. Best Practices for Destructors in C++
  10. Conclusion
  11. 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.

MDN

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.

ParameterConstructorDestructor
PurposeInitializes an objectDestroys an object
NameSame as class nameSame as class name with ~
ParametersCan have parametersCannot have parameters
OverloadingCan be overloadedCannot be overloaded
Call timeCalled when object is createdCalled when object is destroyed
Return typeNo return typeNo return type

Applications of Destructors in C++

  1. 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.

  1. 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.

  1. 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.

  1. 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.

  1. 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.

  1. 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.

MDN

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.

Success Stories

Did you enjoy this article?

Schedule 1:1 free counselling

Similar Articles

Loading...
Get in Touch
Chat on Whatsapp
Request Callback
Share logo Copy link
Table of contents Table of contents
Table of contents Articles
Close button

  1. What Is a Destructor in C++?
  2. Properties of Destructors in C++
  3. Types of Destructors in C++ With Examples
    • Default Destructor
    • User-Defined Destructor
    • Virtual Destructor
    • Pure Virtual Destructor
  4. Functional Classifications Based on Object Lifetime
  5. Modern Destructor Definitions in C++11 and Later
  6. 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
  7. Destructor vs Constructor in C++
  8. Applications of Destructors in C++
  9. Best Practices for Destructors in C++
  10. Conclusion
  11. FAQs
    • Can a destructor in C++ be overloaded?
    • Why do we use virtual destructors in C++?
    • When is a destructor automatically called in C++?