C++ Constructors and Destructors

A constructor runs when an object is created. It has the same name as the class and no return type. A destructor runs when the object is destroyed, and its name is the class name with ~.

#include <iostream>
#include <string>

class Student {
public:
    Student() : name("Unknown"), marks(0) {
        std::cout << "default constructor\n";
    }
    Student(std::string n, int m) : name(std::move(n)), marks(m) {     // initializer list
        std::cout << "constructor: " << name << '\n';
    }
    ~Student() {
        std::cout << "destructor: " << name << '\n';
    }
private:
    std::string name;
    int marks;
};

int main() {
    Student a;
    Student b("Riya", 88);
    std::cout << "end of main\n";
}
Output

default constructor
constructor: Riya
end of main
destructor: Riya
destructor: Unknown

The destructors run in the reverse order of creation, when the objects go out of scope. This is the base of RAII.

Member initializer list

Write : name(n), marks(m) to initialize the members before the constructor body. It is faster for objects, and it is required for const members and references.

The copy constructor

#include <iostream>

class Point {
public:
    Point(int x, int y) : x(x), y(y) {}
    Point(const Point& other) : x(other.x), y(other.y) {
        std::cout << "copied\n";
    }
    int x, y;
};

int main() {
    Point a(1, 2);
    Point b = a;                  // the copy constructor
    b.x = 99;
    std::cout << a.x << ' ' << b.x << '\n';
}
Output

copied
1 99

default, delete and explicit

class NoCopy {
public:
    NoCopy() = default;                         // ask the compiler to make it
    NoCopy(const NoCopy&) = delete;             // copying is forbidden
};

int main() {
    NoCopy a;
    NoCopy b = a;
}
Output

Delete.cpp: In function 'int main()':
Delete.cpp:9:16: error: use of deleted function 'NoCopy::NoCopy(const NoCopy&)'
9 | NoCopy b = a;
| ^
Delete.cpp:4:5: note: declared here
4 | NoCopy(const NoCopy&) = delete; // copying is forbidden
| ^~~~~~
Delete.cpp:9:16: note: use '-fdiagnostics-all-candidates' to display considered candidates
9 | NoCopy b = a;
| ^
Delete.cpp:9:12: warning: unused variable 'b' [-Wunused-variable]
9 | NoCopy b = a;
| ^

  • = default: use the compiler generated version.
  • = delete: forbid this function.
  • explicit: a constructor with one parameter can not be used for hidden conversions.

The Rule of Zero

If your class only has members like std::string, std::vector and smart pointers, you do not write a destructor or a copy constructor. The compiler versions are correct. Write them only when the class directly owns a resource (see Move Semantics).

Delegating constructors

#include <iostream>
#include <string>

class Book {
public:
    Book() : Book("Unknown", 0) {}                 // calls the other constructor
    Book(std::string t, double p) : title(std::move(t)), price(p) {}
    void show() const { std::cout << title << " Rs. " << price << '\n'; }
private:
    std::string title;
    double price;
};

int main() {
    Book().show();
    Book("C++ Basics", 399).show();
}
Output

Unknown Rs. 0
C++ Basics Rs. 399

Note: Always initialize members, and prefer the initializer list. Next: C++ Access Specifiers and Encapsulation.

Congratulations! Chapter Finished. Learn more about the similar topics:
Exercises & Assignments
No Content Found.
Interview Questions & Answers
No Content Found.