OSC++.016: Constructors and Destructors Basics

Minimal black and neon-green illustration representing C++ object construction and destruction.

Constructors prepare a C++ object when it is created. Destructors perform cleanup when that object’s lifetime ends.

This lesson builds on OSC++.008: Classes and Objects and OSC++.009: Member Functions. Those lessons showed how data and functions live inside a class. Constructors and destructors add object-lifecycle behavior.

Constructor basics

A constructor is a special member function whose name matches the class name. It has no return type. C++ calls it automatically when an object is created.

#include <iostream>
#include <string>

class Miner {
public:
    std::string name;
    int hashrate;

    Miner() {
        name = "Unknown";
        hashrate = 0;
        std::cout << "Miner created\n";
    }
};

int main() {
    Miner unit;
    std::cout << unit.name << " " << unit.hashrate << '\n';
}

When unit is created, the constructor runs automatically. The object starts with known values instead of uninitialized data.

Video 1: Constructors explained

Bro Code explains C++ constructors with beginner-friendly class examples.

Parameterized constructors

A constructor can accept arguments so each object starts with different values.

#include <iostream>
#include <string>

class Miner {
public:
    std::string name;
    int hashrate;

    Miner(const std::string& minerName, int ths)
        : name(minerName), hashrate(ths) {
    }
};

int main() {
    Miner s21("S21", 200);
    Miner testRig("Lab Rig", 15);

    std::cout << s21.name << ": " << s21.hashrate << " TH/s\n";
    std::cout << testRig.name << ": " << testRig.hashrate << " TH/s\n";
}

The text after the colon is a member initializer list. It initializes members before the constructor body runs. This is the preferred way to initialize many C++ data members.

Constructor overloading

A class can have more than one constructor as long as their parameter lists differ.

class Rack {
public:
    int miners;

    Rack() : miners(0) {}
    Rack(int count) : miners(count) {}
};

Rack empty; calls the no-argument constructor. Rack rowA(120); calls the one-argument constructor.

Video 2: Constructors and destructors together

Caleb Curry demonstrates how C++ constructors and destructors fit into object lifetime.

Destructor basics

A destructor has the class name preceded by ~. It has no return type and takes no parameters. C++ calls it automatically when the object’s lifetime ends.

#include <iostream>

class Session {
public:
    Session() {
        std::cout << "Session started\n";
    }

    ~Session() {
        std::cout << "Session ended\n";
    }
};

int main() {
    Session test;
    std::cout << "Program is running\n";
}

The constructor runs when test is created. The destructor runs automatically when test goes out of scope at the end of main.

Scope controls lifetime

int main() {
    std::cout << "A\n";

    {
        Session local;
        std::cout << "B\n";
    }

    std::cout << "C\n";
}

The local object is destroyed at the closing brace of the inner block, before the program reaches C. This is deterministic lifetime: the program knows exactly where automatic objects leave scope.

Why destructors matter

Destructors are commonly used to release resources owned by an object. Examples include files, locks, sockets, or dynamically allocated memory.

Modern C++ often stores resources in standard-library objects such as std::string, std::vector, file streams, and smart pointers. Those objects already manage their own cleanup. Prefer them over manual new/delete when possible.

RAII: resource lifetime follows object lifetime

A major C++ design idea is RAII—Resource Acquisition Is Initialization. An object acquires a resource during construction and releases it during destruction. That ties cleanup to scope instead of relying on the programmer to remember a separate cleanup call.

For example, std::ofstream opens a file and closes it when the stream object is destroyed. The same lifetime principle appears throughout modern C++.

Video 3: Object setup and teardown

Professor Hank Stalica walks through default and overloaded constructors, destructors, and object cleanup.

Order of construction and destruction

For ordinary local objects, construction happens when execution reaches the declaration. Destruction generally occurs in reverse order when the scope ends.

int main() {
    Session first;
    Session second;
}

first is constructed first, then second. At the end of the scope, second is destroyed before first.

A practical class example

#include <iostream>
#include <string>

class MinerMonitor {
private:
    std::string worker;
    int temperature;

public:
    MinerMonitor(const std::string& workerName, int temp)
        : worker(workerName), temperature(temp) {
        std::cout << "Monitoring " << worker << '\n';
    }

    void printStatus() const {
        std::cout << worker << ": "
                  << temperature << " C\n";
    }

    ~MinerMonitor() {
        std::cout << "Stopped monitoring " << worker << '\n';
    }
};

int main() {
    MinerMonitor unit("rack-a-s21-01", 67);
    unit.printStatus();
}

This example does not manage an external resource; the destructor only prints a message so you can see exactly when object cleanup occurs.

Common beginner mistakes

  • Giving a constructor a return type. Constructors have no return type.
  • Misspelling the constructor name so it no longer matches the class.
  • Forgetting the ~ in a destructor.
  • Calling the destructor manually on an ordinary automatic object.
  • Using manual new/delete when a standard container or smart pointer would manage lifetime safely.
  • Assuming every class needs a handwritten destructor. Many classes can use the compiler-generated destructor.

Practice

  1. Create a class named PDU with a default constructor that sets outlets to 0.
  2. Add a parameterized constructor that accepts the number of outlets.
  3. Add a destructor that prints PDU destroyed.
  4. Create two objects in the same scope and observe destruction order.
  5. Create one object inside a nested block and identify exactly when its destructor runs.

Knowledge check

Question: When does a constructor run?
Answer: automatically when an object is created.

Question: How many destructors can a class have?
Answer: one.

Question: What does a member initializer list do?
Answer: it initializes members before the constructor body executes.

Question: What idea ties resource cleanup to object lifetime?
Answer: RAII.

Previous C++ lessons

OSC++.014: File Input and Output Basics

OSC++.013: Strings and Text Basics

OSC++.012: Vector Methods

Further reading

For reference material, review cppreference on constructors and cppreference on destructors.

Key takeaway

Constructors establish a valid starting state. Destructors handle end-of-lifetime cleanup. Together they make object lifetime explicit and prepare you for deeper C++ topics such as encapsulation, inheritance, smart pointers, and resource management.

Leave a comment