CppConstructors & Destructors

Constructors & Destructors

A constructor is a special member function that runs automatically when an object is created. Its job is to put the object into a valid initial state — allocating resources, opening files, or simply assigning sensible starting values to member variables. A destructor is the mirror image: a special member function that runs automatically when the object is destroyed, used to release whatever the constructor acquired.

Default and parameterized constructors

A constructor has the same name as the class and no return type. If you don't write any constructor at all, the compiler generates a default (no-argument) constructor for you that default-initializes members. As soon as you write any constructor, the compiler stops generating that default one automatically.

Default vs. parameterized constructors

CPP
class Rectangle {
public:
    double width;
    double height;

    // Default constructor
    Rectangle() {
        width = 1.0;
        height = 1.0;
    }

    // Parameterized constructor
    Rectangle(double w, double h) {
        width = w;
        height = h;
    }

    double area() const { return width * height; }
};

int main() {
    Rectangle unit;          // uses the default constructor -> 1.0 x 1.0
    Rectangle sheet(8.5, 11); // uses the parameterized constructor
}
The member initializer list

Assigning to members inside the constructor body works, but C++ offers a more direct way: the member initializer list, written after a colon following the parameter list.

Using a member initializer list

CPP
class Rectangle {
public:
    double width;
    double height;

    Rectangle(double w, double h) : width(w), height(h) {
        // body can be empty — members are already initialized above
    }

    double area() const { return width * height; }
};
Note
The initializer list is preferred over assigning inside the body for two reasons: it **initializes** members directly instead of default-constructing them and then immediately overwriting them (more efficient, especially for class-type members), and it is the **only** way to initialize `const` members, reference members, and base-class subobjects — those cannot be assigned to in the constructor body at all.
Destructors

A destructor is named ~ClassName(), takes no parameters, and returns nothing. It is called automatically when an object goes out of scope (for stack objects) or when delete is used on it (for heap objects). This automatic, guaranteed cleanup is the foundation of the RAII idiom (Resource Acquisition Is Initialization) — tying a resource's lifetime to an object's lifetime so it can never be forgotten.

A destructor running automatically

CPP
#include <iostream>

class Logger {
public:
    Logger()  { std::cout << "Logger created\n"; }
    ~Logger() { std::cout << "Logger destroyed\n"; }
};

int main() {
    std::cout << "Before block\n";
    {
        Logger log; // constructor runs here
        std::cout << "Inside block\n";
    } // destructor runs here automatically, as soon as 'log' goes out of scope
    std::cout << "After block\n";
}
Tip
See the dedicated RAII page for how this automatic-cleanup guarantee is used to manage file handles, mutexes, network sockets, and heap memory (smart pointers are the most common real-world example).
When one resource needs careful handling

If a class's destructor has real work to do — closing a file, freeing raw memory obtained with new, releasing a lock — that is a signal to stop and think about what happens when an object of that class is copied. The compiler-generated copy constructor just copies each member, including raw pointers, which usually causes two objects to think they each own (and must free) the same resource.

Rule of Three / Rule of Five (teaser)
As a rule of thumb: if you find yourself writing a custom destructor, you very likely also need a custom copy constructor and copy assignment operator (the **Rule of Three**), and in modern C++, probably a move constructor and move assignment operator too (the **Rule of Five**). The next two pages — Copy Constructor and Move Constructor — explain exactly why.
What's next
  • How the compiler-generated copy constructor works, and why it is dangerous for classes that own resources — see Copy Constructor.

  • How to transfer ownership of a resource cheaply instead of copying it — see Move Constructor.