Destructor

In C++, a destructor is a special member function of a class that is called automatically when an object goes out of scope or is explicitly deleted. Its main purpose is to release resources that the object may have acquired during its lifetime.

Key Features of Destructors

  1. Name: The destructor has the same name as the class, preceded by a tilde (~).
  2. No Parameters: Destructors do not take arguments.
  3. No Return Type: Destructors do not return a value.
  4. Automatic Invocation: Called automatically when an object is destroyed.

Syntax

class MyClass {
public:
    ~MyClass() {
        // Cleanup code
    }
};

Purpose of Destructors

  • Resource Deallocation: Free memory or resources such as file handles, network connections, or database connections.
  • Prevent Memory Leaks: Ensure that resources are properly released, preventing leaks.

Example of Destructor

#include <iostream>

class MyClass {
public:
    int* data;

    // Constructor
    MyClass(int size) {
        data = new int[size];
        std::cout << "Constructor: Memory allocated." << std::endl;
    }

    // Destructor
    ~MyClass() {
        delete[] data;
        std::cout << "Destructor: Memory deallocated." << std::endl;
    }
};

int main() {
    MyClass obj(10);
    return 0;
}

When Destructors are Called

  1. Scope Ends: When the object goes out of scope.
  2. Explicit Deletion: When delete is called on a dynamically allocated object.
  3. Program Termination: At the end of the program for static and global objects.
  4. Exception Handling: When an exception is thrown and the stack unwinds.

Virtual Destructors

If a class has virtual functions, it should also have a virtual destructor to ensure proper cleanup when dealing with polymorphism.

class Base {
public:
    virtual ~Base() {
        std::cout << "Base destructor" << std::endl;
    }
};

class Derived : public Base {
public:
    ~Derived() {
        std::cout << "Derived destructor" << std::endl;
    }
};

int main() {
    Base* obj = new Derived();
    delete obj; // Correctly calls Derived and then Base destructor
    return 0;
}

Summary

  • Destructor: Cleans up resources when an object is destroyed.
  • Automatic: Called automatically, no need to invoke explicitly.
  • Memory Management: Essential for resource management and preventing memory leaks.
  • Virtual Destructors: Necessary for proper cleanup in inheritance hierarchies involving polymorphism.