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
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
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; }
};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
#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";
}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.
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.