A destructor is a special member function of a class that is called if an object of that class gets out of scope or when the delete expression is used on a pointer to that class's object. A destructor will have the same name as the class, but it will be prefixed with a tilde (), and it will not be able to return any value or take any parameters. Destructor can be extremely useful for releasing resizable objects.

Destructor is useful for releasing resources before exiting a program, such as closing files and releasing memories.

Want a Top Software Development Job? Start Here!

Full Stack Developer - MERN StackExplore Program
Want a Top Software Development Job? Start Here!

Use of C++ Destructor

In C++, destructors play a crucial role in resource management, ensuring that resources allocated by an object are properly released when the object is no longer needed. Here are some of the primary uses of C++ destructors:

1. Memory Deallocation

Destructors are commonly used to deallocate memory that was allocated during the lifetime of an object. This prevents memory leaks by ensuring that dynamically allocated memory is properly freed.

class MyClass {

private:

    int* data;

public:

    MyClass(int size) {

        data = new int[size]; // allocate memory

    }

    ~MyClass() {

        delete[] data; // free allocated memory

    }

};

2. Resource Release

Destructors release other types of resources, such as file handles, network connections, or database connections, which were acquired during the object's lifetime.

#include <fstream>

class FileHandler {

private:

    std::ofstream file;

public:

    FileHandler(const std::string& filename) {

        file.open(filename);

    }

    ~FileHandler() {

        if (file.is_open()) {

            file.close(); // close the file if open

        }

    }

};

3. Logging and Debugging

Destructors can be used to log messages or perform other debugging activities when an object is destroyed. This can help in tracking the program's behavior and identifying potential issues.

#include <iostream>

class Logger {

public:

    Logger() {

        std::cout << "Logger created." << std::endl;

    }

    ~Logger() {

        std::cout << "Logger destroyed." << std::endl;

    }

};

4. Smart Pointers

Destructors are integral to the implementation of smart pointers, which manage the lifetime of dynamically allocated objects and ensure proper cleanup when the pointer is no longer needed.

#include <memory>

class Resource {

public:

    Resource() {

        std::cout << "Resource acquired." << std::endl;

    }

    ~Resource() {

        std::cout << "Resource released." << std::endl;

    }

};

void useResource() {

    std::unique_ptr<Resource> res(new Resource()); // Resource is automatically released

}

5. Preventing Resource Leaks in Exception Handling

Destructors help in preventing resource leaks by ensuring that resources are released even if an exception occurs. This is crucial in exception-safe programming.

class ExceptionSafe {

private:

    int* data;

public:

    ExceptionSafe(int size) {

        data = new int[size];

        if (size < 0) {

            throw std::runtime_error("Negative size not allowed");

        }

    }

    ~ExceptionSafe() {

        delete[] data; // will be called even if constructor throws an exception

    }

};

6. Custom Cleanup Logic

Destructors can be used to execute custom cleanup logic specific to the needs of the class, such as resetting static variables, unregistering from observers, or performing other cleanup tasks.

class Observer {

private:

    static int count;

public:

    Observer() {

        ++count;

    }

    ~Observer() {

        --count; // adjust the count when an object is destroyed

    }

    static int getCount() {

        return count;

    }

};

int Observer::count = 0;

C++ Destructor Syntax

1. Declaration

  • The destructor has the same name as the class, prefixed with a tilde (~).
  • It does not take any arguments and does not return a value.

class ClassName {

public:

    ~ClassName(); // Destructor declaration

};

2. Definition

  • The destructor can be defined inside or outside the class definition.
  • Inside the class definition:

class ClassName {

public:

    ~ClassName() {

        // Destructor code

    }

};

  • Outside the class definition:

class ClassName {

public:

    ~ClassName(); // Destructor declaration

};

ClassName::~ClassName() {

    // Destructor code

}

Example

#include <iostream>

class MyClass {

public:

    MyClass() {

        std::cout << "Constructor called." << std::endl;

    }

    ~MyClass() {

        std::cout << "Destructor called." << std::endl;

    }

};

int main() {

    MyClass obj; // Constructor is called here

    // Destructor will be called automatically when obj goes out of scope

    return 0;

}

Properties of C++ Destructor

1. Name and Syntax

  • A destructor has the same name as the class but is preceded by a tilde (~).
  • It does not take any arguments and does not return a value.
  • Syntax: ~ClassName();

2. Automatic Invocation

  • The destructor is called automatically when an object goes out of scope or is explicitly deleted using the delete keyword.
  • You do not need to (and should not) explicitly call a destructor in your code.

3. No Parameters

Destructors cannot take parameters, and there can only be one destructor per class.

4. No Return Type

Destructors do not have a return type, not even void.

5. Virtual Destructors

  • If a class intends to be used as a base class, its destructor should be declared virtual. This ensures that the destructor of the derived class is called when an object is deleted through a base class pointer.
  • Syntax: virtual ~BaseClass();

6. Order of Destruction

  • Destructors are called in the reverse order of the constructors. This means that the destructor of a derived class is called first, followed by the destructors of its base classes.
  • Member objects are destroyed after the destructor of the containing object runs.

7. Resource Release

  • Destructors are typically used to release resources such as dynamically allocated memory, file handles, network connections, etc.
  • Properly implementing destructors is crucial to avoid resource leaks.

8. Non-Inheritance

Destructors are not inherited. Each class has its own destructor, and the derived class destructor does not override the base class destructor. However, declaring the base class destructor as virtual ensures proper cleanup.

When Is a Destructor Called?

A destructor in C++ is called in several situations, each corresponding to different phases in an object's lifecycle. Understanding these scenarios is crucial for effective resource management and ensuring that cleanup operations are performed correctly. Here are the primary situations when a destructor is called:

  1. When an Object Goes Out of Scope
  2. When a Dynamically Allocated Object is Deleted
  3. When an Array of Objects is Deleted
  4. When a Static Object's Lifetime Ends
  5. When an Object in a Container is Destroyed
  6. When an Object is Explicitly Destroyed Using std::unique_ptr or std::shared_ptr

C++ Destructor Overloading

The destructor cannot be overloaded. It is not possible to overwhelm the destructor. In a class, we can only have one destructor. In a class followed by a class name, there can only be one destructor with no parameters and no return type.

Default Destructor and User-Defined C++ Destructor

If we don't write our own destructor in the class, the compiler generates one for us. If we have dynamically allocated memory or a pointer in the class, the default destructor works fine. We can write a destructor to release memory before the class instance is destroyed when a class includes a pointer to memory allocated in the class. To prevent memory leaks, this must be done.

Want a Top Software Development Job? Start Here!

Full Stack Developer - MERN StackExplore Program
Want a Top Software Development Job? Start Here!

Virtual C++ Destructor

When we have a virtual feature, it is always a good idea to render destructors virtual in the base class. Deleting a derived class object with a non-virtual destructor using a pointer of base class type causes undefined actions. A virtual destructor should be specified in the base class to correct this situation. Following a program, for example, results in undefined actions.

Sample Code For Virtual Destructor

#include <iostream>

class Base {

public:

    Base() {

        std::cout << "Base constructor called." << std::endl;

    }

    // Virtual destructor

    virtual ~Base() {

        std::cout << "Base destructor called." << std::endl;

    }

};

class Derived : public Base {

public:

    Derived() {

        std::cout << "Derived constructor called." << std::endl;

    }

    ~Derived() {

        std::cout << "Derived destructor called." << std::endl;

    }

};

int main() {

    Base* obj = new Derived(); // Polymorphic behavior

    delete obj; // Calls both Derived and Base destructors

    return 0;

}

Output

The expected output of the program will be:

Base constructor called.

Derived constructor called.

Derived destructor called.

Base destructor called.

Want a Top Software Development Job? Start Here!

Full Stack Developer - MERN StackExplore Program
Want a Top Software Development Job? Start Here!

Rules for C++ Destructors

According to C++ destructor the statement should begin with a tilde () and the same class name.

  1. Destructors are not equipped with parameters or a return form.
  2. Destructors are invoked automatically and cannot be invoked manually from a program.
  3. Destructors cannot be overloaded.
  4. Which can be a virtual destructor.
  5. The Destructor will execute the reverse order of object creation.
  6. Destructor always present only in the public section.
Accelerate your career as a skilled MERN Stack Developer by enrolling in a unique Full Stack Developer - MERN Stack Master's program. Get complete development and testing knowledge on the latest technologies by opting for the MERN Stack Developer Course. Contact us TODAY!

Want a Top Software Development Job? Start Here!

Full Stack Developer - MERN StackExplore Program
Want a Top Software Development Job? Start Here!

Conclusion

C++ destructors are class members that remove an object. They are named when the class object is no longer in view, for example, when a method, a program, or a delete variable is called. Destructors vary from member functions in that they do not accept any arguments and do not return anything. Destructors are also given the same name as their class.

If you are interested in 360-degree learning on full stack development, explore Simplilearn’s Full Stack Developer - MERN Stack Masters program. This gives you all the job-ready knowledge and practical training you need to become a professional full-stack developer today.

Our Software Development Courses Duration And Fees

Software Development Course typically range from a few weeks to several months, with fees varying based on program and institution.

Program NameDurationFees
Caltech Coding Bootcamp

Cohort Starts: 16 Dec, 2024

6 Months$ 8,000
Automation Test Engineer Masters Program

Cohort Starts: 18 Dec, 2024

8 months$ 1,499
Full Stack Java Developer Masters Program

Cohort Starts: 18 Dec, 2024

7 months$ 1,449
Full Stack (MERN Stack) Developer Masters Program

Cohort Starts: 8 Jan, 2025

6 Months$ 1,449