Constructors and Destructors in C++: A Complete Guide for Beginners

Constructors and Destructors in C++: A Complete Guide for Beginners

When students begin learning Object-Oriented Programming (OOP) in C++, one of the first important concepts they encounter is constructors and destructors in C++.

At first, these concepts may look like ordinary functions. However, constructors and destructors have a special role: they help manage the complete lifecycle of an object.

A constructor prepares an object when it is created, while a destructor performs cleanup when the object is no longer required.

This becomes especially important in embedded systems. Embedded applications often work with limited memory, hardware resources, communication interfaces, sensors, and dynamically allocated resources. Understanding how objects are initialized and cleaned up can help developers write more organized and reliable C++ programs.

In this guide, let us understand constructors and destructors step by step, just as we would discuss them in an embedded C++ classroom.

Constructors and destructors in C++ are special member functions used to manage the lifecycle of an object.

  • A constructor is automatically called when an object is created.
  • It is mainly used to initialize object data and prepare the object for use.
  • A destructor is automatically called when an object is destroyed or goes out of scope.
  • It is commonly used for cleanup operations and releasing resources.

In simple terms:

Constructor = Object starts its life

Destructor = Object finishes its life

What Is a Constructor in C++?

A constructor is a special member function of a class that is automatically called when an object is created.

The main purpose of a constructor is to initialize the data members of an object.

For example, imagine an embedded system containing a temperature sensor object. Before reading temperature values, the program may need to initialize variables, communication settings, or hardware-related parameters.

A constructor provides a structured way to perform such initialization when the object is created.

Important Characteristics of a Constructor

A constructor:

  • Has the same name as the class.
  • Does not have a return type.
  • Is automatically called when an object is created.
  • Can initialize class data members.
  • Can be overloaded.
  • Can be defined inside or outside the class.

The basic concept is simple: when an object is created, the constructor runs automatically.

Basic Constructor Syntax in C++

 
cpp
class Device
{
public:
    Device()
    {
        // Initialization code
    }
};

Now, when an object is created:

 
cpp
Device d1;

The constructor Device() is automatically called.

Unlike a normal member function, you do not need to call the constructor separately after creating the object.

Constructor Example in C++

Let us understand this with a simple example.

 
cpp
#include 
using namespace std;

class Book
{
private:
    int pages;

public:
    Book()
    {
        pages = 250;

        cout << "Book object created" << endl;
        cout << "Number of pages: " << pages << endl;
    }
};

int main()
{
    Book b;

    return 0;
}

How Does This Program Work?

When the statement below is executed:

 
cpp
Book b;

the object b is created.

Immediately, the constructor Book() is called automatically.

Inside the constructor:

 
cpp
pages = 250;

the member variable is initialized.

This is an example of a default constructor because no arguments are passed to the constructor.

Constructor vs Normal Function in C++

Students often ask an important question:

If a constructor contains code just like a function, how is it different from a normal function?

The answer is that constructors have special rules and are automatically connected to the lifecycle of an object.

ConstructorNormal Function
Has the same name as the classCan have a different name
Does not have a return typeUsually has a return type or void
Called automatically when an object is createdUsually called explicitly
Used mainly for object initializationUsed to perform specific operations
Cannot be virtualA member function can be virtual

The most important difference is automatic execution.

A normal function is generally called by the programmer. A constructor is automatically called when the corresponding object is created.

Types of Constructors in C++

The commonly discussed types of constructors are:

  • Default Constructor
  • Parameterized Constructor
  • Copy Constructor

Each type is useful in different programming situations.

1. Default Constructor

A default constructor is a constructor that does not take arguments. It can initialize an object with predefined or default values.

Example

 
cpp
#include 
using namespace std;

class Sensor
{
private:
    int sensorID;

public:
    Sensor()
    {
        sensorID = 101;

        cout << "Sensor ID: " << sensorID << endl;
    }
};

int main()
{
    Sensor s1;

    return 0;
}

When s1 is created, the constructor automatically initializes sensorID.

Why Is This Useful in Embedded Systems?

Suppose you create an object representing a device. You may want every new object to begin with safe default values.

For example:

 
cpp
Device()
{
    status = 0;
    errorCode = 0;
}

This helps ensure that the object begins in a predictable state.

In embedded programming, predictable initialization is important because uninitialized values can cause unexpected system behaviour.

2. Parameterized Constructor

A parameterized constructor accepts arguments when an object is created. This allows different objects to be initialized with different values.

Example

 
cpp
#include 
using namespace std;

class Motor
{
private:
    int speed;

public:
    Motor(int s)
    {
        speed = s;
    }

    void display()
    {
        cout << "Motor Speed: " << speed << endl;
    }
};

int main()
{
    Motor m1(1000);

    m1.display();

    return 0;
}

Here:

 
cpp
Motor m1(1000);

creates the object and passes 1000 to the constructor. The constructor then initializes the speed variable.

Example: Calculating Values Using a Parameterized Constructor

 
cpp
#include 
using namespace std;

class Bar
{
private:
    int drink;
    int people;

public:
    Bar(int d, int p)
    {
        drink = d;
        people = p;
    }

    int totalCash()
    {
        return drink * people;
    }
};

int main()
{
    Bar b(40, 35);

    cout << "Total Cash Collected: "
         << b.totalCash();

    return 0;
}

The constructor receives:

  • 40 for drink
  • 35 for people

These values are stored in the object and later used by the totalCash() function.

Parameterized constructors are useful whenever objects require different initial values.

3. Copy Constructor in C++

A copy constructor creates a new object by initializing it from another object of the same class.

In simple terms: one object is used as the source for creating another object.

The general syntax is:

 
cpp
ClassName(const ClassName &object)
{
    // Copy data
}

Example

 
cpp
#include 
using namespace std;

class Sensor
{
private:
    int value;

public:
    Sensor(int v)
    {
        value = v;
    }

    Sensor(const Sensor &obj)
    {
        value = obj.value;
    }

    void display()
    {
        cout << "Sensor Value: "
             << value << endl;
    }
};

int main()
{
    Sensor s1(25);

    Sensor s2 = s1;

    s2.display();

    return 0;
}

In this example:

 
cpp
Sensor s2 = s1;

uses s1 to initialize s2. The copy constructor copies the value from one object to another.

Copy constructors become particularly important when classes manage resources such as dynamically allocated memory or other resources that require careful copying.

What Is Constructor Overloading?

Just like normal functions, constructors can also be overloaded.

Constructor overloading means creating multiple constructors with the same name but different parameters. The compiler determines which constructor should be called based on the number or types of arguments provided.

Example

 
cpp
#include 
using namespace std;

class Overload
{
private:
    int result;

public:

    Overload(int x, int y)
    {
        result = x * y;
    }

    Overload(int x, int y, int z)
    {
        result = x + y + z;
    }

    int getResult()
    {
        return result;
    }
};

int main()
{
    Overload o1(20, 4);
    Overload o2(50, 65, 30);

    cout << "Result 1: "
         << o1.getResult() << endl;

    cout << "Result 2: "
         << o2.getResult() << endl;

    return 0;
}

The first object:

 
cpp
Overload o1(20, 4);

calls the constructor with two parameters.

The second object:

 
cpp
Overload o2(50, 65, 30);

calls the constructor with three parameters.

This flexibility is useful when an object can be initialized in different ways.

What Is a Destructor in C++?

A destructor is another special member function of a class.

While a constructor is called when an object is created, a destructor is automatically called when an object is destroyed or goes out of scope.

The destructor is commonly used to perform cleanup operations.

Destructor Characteristics

A destructor:

  • Has the same name as the class.
  • Uses a tilde (~) before the class name.
  • Does not have a return type.
  • Does not accept arguments.
  • Is automatically called when an object’s lifetime ends.

The syntax is:

 
cpp
~ClassName()
{
    // Cleanup code
}

Destructor Example in C++

 
cpp
#include 
using namespace std;

class FormulaOne
{
private:
    int speed;
    int pickup;

public:

    FormulaOne(int s, int p)
    {
        cout << "Constructor called" << endl;

        speed = s;
        pickup = p;
    }

    void display()
    {
        cout << "Speed: " << speed << endl;
        cout << "Pickup: " << pickup << endl;
    }

    ~FormulaOne()
    {
        cout << "Destructor called" << endl;
    }
};

int main()
{
    FormulaOne f(370, 4);

    f.display();

    return 0;
}

Expected Execution Flow

When the program creates:

 
cpp
FormulaOne f(370, 4);

the constructor runs first. The object is initialized with:

  • Speed = 370
  • Pickup = 4

The display() function then prints the values.

When the object goes out of scope at the end of main(), the destructor is automatically called.

The execution sequence is therefore:

  1. Object is created.
  2. Constructor is called.
  3. Object performs its required operations.
  4. Object reaches the end of its lifetime.
  5. Destructor is called.

Difference Between Constructor and Destructor in C++

Constructors and destructors are special member functions that manage the lifecycle of an object, but they perform opposite roles.

ConstructorDestructor
Initializes an object when it is created.Performs cleanup when an object is destroyed.
Has the same name as the class.Has the class name preceded by ~.
Can have parameters.Cannot have parameters.
Can be overloaded.Cannot be overloaded.
Called automatically when an object is created.Called automatically when an object goes out of scope or is deleted.
Used to initialize data members and acquire resources.Used to release resources and perform cleanup.
A class can have multiple constructors.A class can have only one destructor.

Example

 
cpp
class Student {
public:
    Student() {
        cout << "Constructor called";
    }

    ~Student() {
        cout << "Destructor called";
    }
};

Here, the constructor runs when the Student object is created, while the destructor runs when the object is destroyed.

Constructors and Destructors in Embedded Systems

Now let us connect this concept with embedded systems programming.

In embedded C++ applications, classes may represent:

  • Sensors
  • Motors
  • Communication interfaces
  • UART modules
  • SPI devices
  • I2C peripherals
  • GPIO controllers
  • Timers
  • Display modules

A constructor can be used to initialize the software state of these objects. For example:

 
cpp
class Motor
{
public:

    Motor()
    {
        // Initialize default state
    }
};

Similarly, a destructor can be used for cleanup associated with the object’s lifetime.

However, embedded developers must carefully understand resource usage. Embedded systems often have limited memory and strict timing requirements, so object creation, dynamic memory allocation, copying, and cleanup should be designed carefully according to the system requirements.

A Simple Embedded System Example

Consider a simplified sensor class.

 
cpp
#include 
using namespace std;

class TemperatureSensor
{
private:
    int sensorID;

public:

    TemperatureSensor(int id)
    {
        sensorID = id;

        cout << "Sensor initialized: "
             << sensorID << endl;
    }

    void readSensor()
    {
        cout << "Reading sensor: "
             << sensorID << endl;
    }

    ~TemperatureSensor()
    {
        cout << "Sensor object cleanup completed"
             << endl;
    }
};

int main()
{
    TemperatureSensor sensor1(101);

    sensor1.readSensor();

    return 0;
}

This example demonstrates the complete object lifecycle.

When sensor1 is created:

 
cpp
TemperatureSensor sensor1(101);

the constructor initializes the object. The program then uses:

 
cpp
sensor1.readSensor();

Finally, when the object goes out of scope, the destructor is called automatically.

Constructor and Destructor Execution Order

Understanding execution order is important.

For a simple object:

 
cpp
Device d1;

the constructor executes when the object is created. When the object leaves its scope, the destructor executes.

 
Object Created
      ↓
Constructor Called
      ↓
Object Used
      ↓
Object Lifetime Ends
      ↓
Destructor Called

This lifecycle management is one of the fundamental ideas behind Object-Oriented Programming in C++.

Important Points to Remember

When working with constructors and destructors in C++, remember these points:

Constructor

  • Same name as the class.
  • No return type.
  • Called automatically when an object is created.
  • Used to initialize objects.
  • Can accept parameters.
  • Can be overloaded.

Destructor

  • Same name as the class with ~.
  • No return type.
  • Does not accept arguments.
  • Called automatically when an object is destroyed or goes out of scope.
  • Used for cleanup operations.

Final Thoughts

Understanding constructors and destructors in C++ is essential for every student learning Object-Oriented Programming and embedded C++ development.

A constructor helps ensure that an object starts with the required initial state. A destructor helps manage cleanup when that object’s lifetime ends.

As you move deeper into embedded systems, these concepts become part of larger topics such as object lifetime, memory management, hardware abstraction, resource management, and C++ application design.

The best way to master constructors and destructors is not just to memorize their definitions. Create small classes, initialize objects in different ways, experiment with parameterized and copy constructors, overload constructors, and observe exactly when destructors are called.

Once you understand the lifecycle of an object, many advanced C++ and embedded systems concepts become easier to understand.

FAQs

A constructor initializes an object when it is created. A destructor performs cleanup when the object reaches the end of its lifetime.

Yes. A parameterized constructor can accept values during object creation.

Example:

Motor m1(1000);

Yes. Multiple constructors can have the same class name as long as their parameter lists are different.

No. A destructor does not take arguments.

A destructor is automatically called when an object’s lifetime ends, such as when a local object goes out of scope.

Author

Embedded Systems and IOT Trainer– IIES

Updated On: 31-08-26


10+ years of hands-on experience delivering practical training in Embedded Systems and it's design