In C++, there are several types of constructors, each serving a different purpose. Constructors can be classified based on in which situations they are being used. There are 4 types of constructors in C++:
- Default Constructor: No parameters. They are used to create an object with default values.
- Parameterized Constructor: Takes parameters. Used to create an object with specific initial values.
- Copy Constructor: Takes a reference to another object of the same class. Used to create a copy of an object.
- Move Constructor: Takes an rvalue reference to another object. Transfers resources from a temporary object.
Types of Constructors in C++Let us look into each type in detail:
A default constructor is a constructor that doesn’t take any argument. It has no parameters. It is also called a zero-argument constructor.
Syntax of Default Constructor
className() {
// body_of_constructor
}
Examples of Default Constructor
The below examples demonstrate how to use the default constructors in C++.
Example 1:
C++
// C++ program to illustrate the concept of default
// constructors
#include <iostream>
using namespace std;
class construct {
public:
int a, b;
// Default Constructor
construct()
{
a = 10;
b = 20;
}
};
int main()
{
// Default constructor called automatically
// when the object is created
construct c;
cout << "a: " << c.a << endl << "b: " << c.b;
return 1;
}
Note: Even if we do not define any constructor explicitly, the compiler will automatically provide a default constructor implicitly.
Example 2:
C++
// C++ program to demonstrate the implicit default
// constructor
#include <iostream>
using namespace std;
// class
class student {
int rno;
char name[50];
double fee;
public:
};
int main()
{
// creating object without any parameters
student s;
return 0;
}
As we can see, we are able the object of class student is created without passing any argument even when we haven’t defined any explicit default constructor for it.
Application & Use:
- Used when you need an object to be initialized with default values.
- It is automatically called when an object is created without any parameters.
Advantages:
- Provides a way to initialize members with default values.
- Ensures objects are in a valid state when created.
Disadvantages:
- Might not be useful if an object requires specific initial values.
2. Parameterized Constructor in C++
Parameterized Constructors make it possible to pass arguments to constructors. Typically, these arguments help initialize an object when it is created. To create a parameterized constructor, simply add parameters to it the way you would to any other function. When you define the constructor’s body, use the parameters to initialize the object.
Syntax of Parameterized Constructor
className (parameters...) {
// body
}
Examples of Parameterized Constructor
The below examples demonstrate how to use the parameterized constructors in C++.
Example 1: Defining Parameterized Constructor Inside the Class.
C++
// CPP program to illustrate parameterized constructors
#include <iostream>
using namespace std;
class Point {
private:
int x, y;
public:
// Parameterized Constructor
Point(int x1, int y1)
{
x = x1;
y = y1;
}
int getX() { return x; }
int getY() { return y; }
};
int main()
{
// Constructor called
Point p1(10, 15);
// Access values assigned by constructor
cout << "p1.x = " << p1.getX()
<< ", p1.y = " << p1.getY();
return 0;
}
Outputp1.x = 10, p1.y = 15
Example 2: Defining Parameterized Constructor Outside the Class.
C++
// C++ Program to illustrate how to define the parameterized
// constructor outside the class
#include <iostream>
#include <string.h>
using namespace std;
// class definition
class student {
int rno;
char name[50];
double fee;
public:
student(int, char[], double);
void display();
};
// parameterized constructor outside class
student::student(int no, char n[], double f)
{
rno = no;
strcpy(name, n);
fee = f;
}
void student::display()
{
cout << endl << rno << "\t" << name << "\t" << fee;
}
// driver code
int main()
{
student s(1001, "Ram", 10000);
s.display();
return 0;
}
Example 3:
When an object is declared in a parameterized constructor, the initial values have to be passed as arguments to the constructor function. The normal way of object declaration may not work. The parameterized constructors can be called explicitly or implicitly:
Example e = Example(0, 50); // Explicit call
Example e(0, 50); // Implicit call
When the parameterized constructor is defined and no default constructor is defined explicitly, the compiler will not implicitly create the default constructor and hence create a simple object as:
Student s;
will flash an error.
C++
// C++ Program to illustrate the error caused be not
// defining the explicit defualt constructor after
// parameterized constructor
#include <iostream>
#include <string.h>
using namespace std;
// class definition
class student {
int rno;
char name[50];
double fee;
public:
student(int no, char n[], double f)
{
rno = no;
strcpy(name, n);
fee = f;
}
};
// driver code
int main()
{
student s; // this will cause error
return 0;
}
Output
main.cpp: In function ‘int main()’:
main.cpp:25:13: error: no matching function for call to ‘student::student()’
25 | student s; // this will cause error
| ^
main.cpp:14:5: note: candidate: ‘student::student(int, char*, double)’
14 | student(int no, char n[], double f)
| ^~~~~~~
main.cpp:14:5: note: candidate expects 3 arguments, 0 provided
main.cpp:8:7: note: candidate: ‘constexpr student::student(const student&)’
8 | class student {
| ^~~~~~~
main.cpp:8:7: note: candidate expects 1 argument, 0 provided
main.cpp:8:7: note: candidate: ‘constexpr student::student(student&&)’
main.cpp:8:7: note: candidate expects 1 argument, 0 provided ^~
Important Note: Whenever we define one or more non-default constructors( with parameters ) for a class, a default constructor( without parameters ) should also be explicitly defined as the compiler will not provide a default constructor in this case. However, it is not necessary but it’s considered to be the best practice to always define a default constructor.
Application & Use:
- Used when you need to initialize objects with specific values.
- Allows passing parameters to set initial states of objects.
Advantages:
- Provides flexibility to initialize objects with different values.
- Allows for more meaningful initialization.
Disadvantages:
- If not combined with a default constructor, it might make it necessary to always provide parameters when creating objects.
Default Arguments with C++ Parameterized Constructor
Just like normal functions, we can also define default values for the arguments of parameterized constructors. All the rules of the default arguments will be applied to these parameters.
Example 3: Defining Parameterized Constructor with Default Values
C++
// C++ Program to illustrate how to use default arguments
// with parameterized constructor
#include <iostream>
using namespace std;
// class
class GFG {
private:
int data;
public:
// parameterized constructor with default values
GFG(int x = 0) { data = x; }
int getData() { return data; }
};
int main()
{
GFG obj1; // will not throw error
GFG obj2(25);
cout << "First Object Data: " << obj1.getData() << endl;
cout << "Second Object Data: " << obj2.getData()
<< endl;
return 0;
}
OutputFirst Object Data: 0
Second Object Data: 25
As we can see, when the default values are assigned to every argument of the parameterized constructor, it is legal to create the object without passing any parameters just like default constructors. So, this type of constructor works as both a default and parameterized constructor.
3. Copy Constructor in C++
A copy constructor is a member function that initializes an object using another object of the same class.
Syntax of Copy Constructor
Copy constructor takes a reference to an object of the same class as an argument.
ClassName (ClassName &obj)
{
// body_containing_logic
}
Just like the default constructor, the C++ compiler also provides an implicit copy constructor if the explicit copy constructor definition is not present. Here, it is to be noted that, unlike the default constructor where the presence of any type of explicit constructor results in the deletion of the implicit default constructor, the implicit copy constructor will always be created by the compiler if there is no explicit copy constructor or explicit move constructor is present.
Examples of Copy Constructor
The below examples demonstrate how to use the copy constructors in C++.
Example 1: Illustration of Implicit Copy Constructor
C++
// C++ program to illustrate the use of Implicit copy
// constructor
#include <iostream>
using namespace std;
class Sample {
int id;
public:
// parameterized constructor
Sample(int x) { id = x; }
void display() { cout << "ID=" << id; }
};
int main()
{
Sample obj1(10);
obj1.display();
cout << endl;
// creating an object of type Sample from the obj
Sample obj2(obj1); // or obj2=obj1;
obj2.display();
return 0;
}
Example 2: Defining of Explicit Copy Constructor
C++
// C++ Program to demonstrate how to define the explicit
// copy constructor
#include <iostream>
using namespace std;
class Sample {
int id;
public:
// default constructor with empty body
Sample() {}
// parameterized constructor
Sample(int x) { id = x; }
// copy constructor
Sample(Sample& t) { id = t.id; }
void display() { cout << "ID=" << id; }
};
// driver code
int main()
{
Sample obj1(10);
obj1.display();
cout << endl;
// copy constructor called
Sample obj2(obj1); // or obj2=obj1;
obj2.display();
return 0;
}
Example 3: Defining of Explicit Copy Constructor with Parameterized Constructor
C++
// C++ program to demonstrate copy construction along with
// parameterized constructor
#include <iostream>
#include <string.h>
using namespace std;
// class definition
class student {
int rno;
char name[50];
double fee;
public:
student(int, char[], double);
student(student& t) // copy constructor
{
rno = t.rno;
strcpy(name, t.name);
fee = t.fee;
}
void display();
};
student::student(int no, char n[], double f)
{
rno = no;
strcpy(name, n);
fee = f;
}
void student::display()
{
cout << endl << rno << "\t" << name << "\t" << fee;
}
int main()
{
student s(1001, "Manjeet", 10000);
s.display();
student manjeet(s); // copy constructor called
manjeet.display();
return 0;
}
Output1001 Manjeet 10000
1001 Manjeet 10000
Application & Use:
- Used when you need to create a new object as a copy of an existing object.
- Essential for proper copying of objects that manage resources like dynamic memory.
Advantages:
- Ensures a deep copy of objects, especially when managing dynamic resources.
- Prevents resource leaks and undefined behavior from shallow copying.
Disadvantages:
- Can be expensive in terms of performance if the object being copied is large.
- Requires careful implementation to ensure all resources are correctly copied.
4. Move Constructor in C++
The move constructor is a recent addition to the family of constructors in C++. It is like a copy constructor that constructs the object from the already existing objects., but instead of copying the object in the new memory, it makes use of move semantics to transfer the ownership of the already created object to the new object without creating extra copies.
It can be seen as stealing the resources from other objects.
Syntax of Move Constructor in C++
className (className&& obj) {
// body of the constructor
}
The move constructor takes the rvalue reference of the object of the same class and transfers the ownership of this object to the newly created object.
Like a copy constructor, the compiler will create a move constructor for each class that does not have any explicit move constructor.
Examples of Move Constructor
The below examples demonstrate how to use the move constructors in C++.
Example 1: Defining Move Constructor
C++
// C++ Program to illustrate how to define a move
// constructor
#include <iostream>
using namespace std;
class Box {
public:
int* data; // Pointer to an integer value
// Constructor
Box(int value)
{
data = new int;
*data = value;
}
// Move constructor
Box(Box&& other) noexcept
{
cout << "Move Constructor Called" << endl;
data = other.data; // Transfer ownership of 'other'
// data
other.data = nullptr; // Null out 'other' to prevent
// double deletion
}
// Destructor
~Box() { delete data; }
};
int main()
{
// Create a Box with value 42
Box originalBox(42);
// Create a new Box by moving resources from the
// originalBox
Box newBox(move(originalBox));
cout << "newBox.data: " << *newBox.data;
// originalBox is now in a valid but unspecified
// state (its resources were moved to newBox)
return 0;
}
OutputMove Constructor Called
newBox.data: 42
Application & Use:
- Used to transfer ownership of resources from a temporary object (rvalue) to a new object.
- Enhances performance by eliminating unnecessary copying of resources.
Advantages:
- Improves performance by avoiding deep copies.
- Efficient resource management, especially for temporary objects.
Disadvantages:
- Requires understanding of rvalue references and move semantics.
- Can introduce complexity in code if not used carefully.
Difference Between different types of Constructors in C++
Parameter | Default Constructor | Parameterized Constructor | Copy Constructor | Move Constructor |
---|
Definition | A constructor that can be called without any arguments. | A constructor that takes arguments to initialize an object with specific values. | A constructor that initializes an object using another object of the same class, performing a deep copy. | Introduced in C++11, a constructor that transfers resources from a temporary object to a new object. |
---|
Syntax | MyClass(); | MyClass(int a); | MyClass(const MyClass& other); | MyClass(MyClass&& other) noexcept; |
---|
When Called | When an object is created without any arguments. | When an object is created with specific initial values. | When an object is created as a copy of another object. | When an object is initialized using an rvalue reference. |
---|
Purpose | To create an object with default values. | To create an object with specific initial values. | To create a copy of an existing object. | To efficiently transfer resources from a temporary object. |
---|
Real life example to understand the Types of Constructors:
Let us understand the types of constructors in C++ by taking a real-world example. Suppose you went to a shop to buy a marker. When you want to buy a marker, what are the options?
- The first one you go to a shop and say give me a marker. So just saying give me a marker means that you did not set which brand name and which color, you didn’t mention anything just say you want a marker. So when we said just I want a marker whatever the frequently sold marker is there in the market or his shop he will simply hand over that. And this is what a default constructor is!
- The second method is you go to a shop and say I want a marker red in color and XYZ brand. So you are mentioning this and he will give you that marker. So in this case you have given the parameters. And this is what a parameterized constructor is!
- Then the third one you go to a shop and say I want a marker like this(a physical marker on your hand). So the shopkeeper will see that marker. Okay, and he will give a new marker for you. So copy of that marker. And that’s what a copy constructor is!
Now, assume that you don’t to buy a new marker but instead take ownership of your friend’s marker. It means taking ownership of already present resources instead of getting a new one. That’s what a move constructor is!
Is Destructor a Type of Constructor in C++?
No, a destructor is not a type of constructor in C++. While both destructors and constructors are special member functions of a class, they serve different purposes.
Purpose:
- A destructor is used to clean up resources when an object goes out of scope or is explicitly deleted.
- It is called automatically when an object is destroyed.
Syntax:
- The destructor has the same name as the class, preceded by a tilde (
~
). - It takes no parameters and has no return type.
class Example {
public:
~Example() {
// Destructor code
}
};
- Function:
- Constructor: Initializes an object.
- Destructor: Cleans up resources before an object is destroyed.
- Number of Parameters:
- Constructor: Can have parameters (default, parameterized, copy, move constructors).
- Destructor: Cannot have parameters.
- Return Type:
- Constructor: Has no return type.
- Destructor: Also has no return type.
- Invocation:
- Constructor: Called when an object is created.
- Destructor: Called when an object is destroyed.
- Name:
- Constructor: Same name as the class.
- Destructor: Same name as the class, but preceded by a tilde (
~
).