Constructors and Destructors in C++

Constructors and Destructors in C++

C++ gives every object a clear life story: it’s created, used, and then destroyed. To make this safe and predictable, the language runs a special function at birth (to initialize the object) and another at death (to clean up resources).

Constructors in C++

Constructors exist to prevent uninitialized state, to let callers pass meaningful values at creation time, and to centralize setup logic in one place. In practice, you’ll use two common kinds;

  • Default (non-parameterized)
  • Parameterized

You may define multiple constructors for the same class (overloading) so the same class can be created in different valid ways.

A constructor in C++ is a special member function with the same name as its class, has no return type, and is invoked automatically when an object is created to initialize its data members.

Syntax and core rules (quick reference)

class ClassName {
public:
    ClassName();                 // default (non-parameterized)
    ClassName(int x, int y);     // parameterized
};
  • The name must exactly match the class; there is no return type.
  • You may overload constructors with different parameter lists.
  • Prefer member-initializer lists (: a(x), b(y)) so members are constructed directly.
  • Members are initialized in the order they are declared in the class, not the order listed in the initializer list.

Program 1 — Default constructor

#include <iostream>
using namespace std;

class Student {
private:
    int a;        // internal/private
public:
    int b;        // visible/public

    // Default constructor: give safe defaults
    Student(){
             a=0;
             b=0 
        }

    void display() const {
        cout << "The value of a and b is: " << a << " and " << b << '\n';
    }
};

int main() {
    Student s;     
    s.display();   
    return 0;
}

What to notice: creating Student s; automatically calls Student(). Using an initializer list builds a and b directly as 0, so there’s no “create-then-assign” waste and no risk of reading garbage values.

Program 2 — Parameterized constructor

#include <iostream>
using namespace std;

class Student {
private:
    int a;
public:
    int b;

    // Parameterized constructor: caller chooses values
    Student(int m, int n) {
            a=m;
            b=n;
      }

    void display() const {
        cout << "The value of a and b is: " << a << " and " << b << '\n';
    }
};

int main() {
    Student s(5, 10);  
    s.display();
    return 0;
}

What to notice: the object starts in a meaningful state chosen by the caller. Initializer lists are especially important for const members, references, or complex objects.

Program 3 — Constructor overloading

#include <iostream>
#include <stdexcept>
using namespace std;

class Student {
private:
    int a;
public:
    int b;

    // 1) Default
    Student(){
             a=0;
             b=0 
        }

    // 2) One-arg (delegates to two-arg)
      Student(int m) {
            a=m;
       }

    // 3) Two-arg with validation
      Student(int m, int n) {
            a=m;
            b=n;
      }

    void display() const {
        cout << "The value of a and b is: " << a << " and " << b << '\n';
    }
};

int main() {
    Student s1;        // (0,0)
    Student s2(7);     // (7,0)
    Student s3(5, 10); // (5,10)
    s1.display();
    s2.display();
    s3.display();
}

What to notice: you can provide several constructors so users of your class have clear, safe options. Delegating constructors help keep logic in one place.

Default vs parameterized

FeatureDefault constructorParameterized constructor
ArgumentsNoneOne or more
InitializationSafe baseline (e.g., zeros)Caller chooses values
FlexibilitySame defaults for all objectsEach object can be different
Example Student(){
a=0;
b=0
}
Student(int m, int n) {
a=m;
b=n;
}
Call siteStudent s;Student s(5,10);

Destructors in C++

C++ also runs a special function at the end of an object’s life so that resources are released safely even if you forget to do it manually.

A destructor in C++ is a special member function with the same name as the class prefixed by ~, has no return type and no parameters, and is invoked automatically when an object goes out of scope or is deleted to perform cleanup (e.g., free memory, close files, release handles).

Destructors exist to prevent leaks or misuse of resources. They’re essential when your class acquires ownership of something that lives outside normal variables—heap memory (new/new[]), file descriptors, sockets, mutexes, database connections, etc. You write at most one destructor per class, and you don’t overload it.

Syntax and core rules (quick reference)

class ClassName {
public:
    ~ClassName();   // declaration
};

ClassName::~ClassName() {
    // cleanup code here
}
  • No parameters, no return type, no overloading.
  • Called automatically on scope exit, or when you delete/delete[] a dynamically allocated object.
  • Destruction order is the reverse of construction: members are destroyed first (in declaration order), then the object itself.

Program 4 — Seeing the destructor run

#include <iostream>
using namespace std;

class Marker {
public:
    Marker()  { cout << "Marker constructed\n"; }
    ~Marker() { cout << "Marker destroyed\n";   }
};

int main() {
    cout << "Entering scope\n";
    {
        Marker m;    // constructor runs here
        cout << "Using m inside scope\n";
    }               // destructor runs automatically here
    cout << "After scope\n";
}

What to notice: the destructor is guaranteed to run when m leaves scope—even if you return early or an exception is thrown—making scope a safety net.

Constructor vs Destructor (quick comparison)

AspectConstructorDestructor
PurposeInitialize object stateRelease resources / cleanup
NameSame as class~ + class name
ParametersAllowed (overloading supported)Not allowed (no overloading)
When calledAt object creationWhen object goes out of scope / is deleted
Count per classMany (overloads)One
Provided by compilerYes (defaulted if none defined)Yes (defaulted if none defined)
Typical dutiesSet defaults, enforce invariants, accept argsFree memory, close files/sockets, release locks

Constructors give objects a correct beginning; destructors give them a safe ending. Use default and parameterized constructors to make creation both safe and convenient, and overload when you want multiple valid ways to build the same class. When your class owns resources, lean on RAII and let the destructor guarantee cleanup, even across errors and early returns. This is the foundation of reliable, modern C++ class design.

Leave a Reply

Your email address will not be published. Required fields are marked *