Among different types of constructors, the copy constructor is the type that uses another object within the same class to initialize the data members of the class within the class. In other words, it creates a copy of an existing object of the class.
- Constructor
- What is a Copy Constructor in C++?
- Classification of Constructors
- Uses of Copy Constructor
- Example of Copy Constructor in C++
- Constructor Copies
- Difference between Copy Constructor and Assignment Operator
Let us begin by first understanding what a constructor is before we dive in what copy constructor in C++ is.
Constructor
A constructor is a special member function used to initialize objects of its class. It will be called automatically when the object is created.
Let us see how a constructor is automatically executed at the time of object creation.
Constructor Program in C++:
#include<iostream>
using namespace std;
class ABC {
public:ABC(){
cout<<"Constructor is called automatically";
cout<<"at the time of execution"<<endl;
}
void display(){
cout<<"hello world";
}
};
int main() {
ABC ob1,ob2;
ob1.display();
ob2.display();
return 0;
}
Output:
In the above program, we created two objects ob1 and ob2, for the same class ABC. As you can see, we have called the display() function to execute, but we didn’t call for constructor ABC().
A constructor is called automatically when we created the object ob1 and ob2, but for display(), we need to call unless we call it won’t execute explicitly. This is the advantage of using the constructor. It is easily accessible, and the user can easily understand the flow of the program.
Let us see the program to find the sum of N natural numbers.
Program:
#include<iostream>
using namespace std;
class sum {
private: int n,s;
public: sum(){
s=0;
cout<<"enter limit= ";
cin>>n;
for(int i=1; i<=n; i++){
s+=i;
cout<<"Sum of natural numbers= "<<s;
}
}
};
int main() {
sum ob1;
return 0;
}
Output:
- In the above example, we created an object ob1 which calls the sum() function automatically.
- We find the sum of the first five natural numbers, i.e., 1 to 5.
- Sum() is the constructor which is automatically called at the time of object creation. It gives us the result as 15 [1+2+3+4+5=15].
What is a Copy Constructor in C++?
Copy constructors are the member functions of a class that initialize the data members of the class using another object of the same class. It copies the values of the data variables of one object of a class to the data members of another object of the same class. A copy constructor can be defined as follows:
class class_name {
Class_name(Class_name &old_object){ //copy constructor
Var_name = old_object.Var_name;
….
….
}
}
A copy constructor in C++ is further categorized into two types:
- Default Copy Constructor
- User-defined Copy Constructor
Default Copy Constructors: When a copy constructor is not defined, the C++ compiler automatically supplies with its self-generated constructor that copies the values of the object to the new object.
Example:
#include <iostream>
using namespace std;
class A {
int x, y;
public:
A(int i, int j)
{
x = i;
y = j;
}
int getX() { return x; }
int getY() { return y; }
};
int main()
{
A ob1(10, 46);
A ob2 = ob1; // 1
cout << "x = " << ob2.getX() << " y = " << ob2.getY();
return 0;
}
Output:
Here, in line 1, even without the copy constructor, the values of ob1’s variable members copy fine to the member variables of ob2.
User-defined Copy Constructors: In case of a user-defined copy constructor, the values of the parameterised object of a class are copied to the member variables of the newly created class object. The initialization or copying of the values to the member variables is done as per the definition of the copy constructor.
Example:
#include <iostream>
using namespace std;
class Example
{
public:
int a;
Example(int x) // parameterized constructor
{
a=x;
}
Example(Example &ob) // copy constructor
{
a = ob.a;
}
};
int main()
{
Example e1(36); // Calling the parameterized constructor
Example e2(e1); // Calling the copy constructor
cout<<e2.a;
return 0;
}
Output
Classification of Constructors
Constructors are classified as follows:
- Parameterized Constructor
- Constructor overloading
- Copy Constructors
- Default Constructor
- Constructor with default arguments.
Let me give a brief introduction to the above topics.
Parameterised constructor:
The constructor that takes arguments or parameters at the time of object creation is known as parameterized constructor. The syntax for calling a parameterised constructor is given below:
Syntax:
ClassName objectName (arg1, arg2 arg3,…, argN);
Example:
#include <iostream>
using namespace std;
class Transport
{
public:
int wheels;
Transport(int n) // parameterized constructor
{
wheels=n;
}
};
int main()
{
Transport car(4); // Calling the parameterized constructor for the 1st object
Transport bike(2); // Calling the parameterized constructor for the 2nd object
cout<<"Car has "<<car.wheels<<" wheels\n";
cout<<"Bike has "<<bike.wheels<<" wheels\n";
return 0;
}
Output:
Constructor overloading:
- When a class contains more than one constructor, it is known as constructor overloading. The constructors are identical in names, so they are distinguished from each other on the basis of the number of arguments and type of arguments in their parameters.
Constructor overloading in C++ represents the polymorphism feature of OOP. The syntax for calling different constructors for different objects of the same class is shown below.
Syntax:
ClassName object1 (arg1, arg2, arg3);
ClassName object2 (arg);
ClassName object3();
The syntax for the definition of multiple constructors corresponding to the above calling of constructors has been given below:
Syntax:
class ClassName (datatype1 arg1, datatype2 arg2, datatype3 arg3){
//body of constructor1
}
ClassName object2 (arg){
//body of constructor2
}
ClassName object3(){
//body of constructor3
}
Example:
#include <iostream>
using namespace std;
class Transport
{
public:
int wheels;
string name;
string color;
string type;
//Constructor Overloading
Transport(int n) // Constructor1
{
wheels=n;
}
Transport(string str1, string str2) //Constructor2
{
name=str1;
color=str2;
}
Transport(string str) //Constructor3
{
type=str;
}
};
int main()
{
Transport car(4); // Calling the 1st constructor
Transport bike("Honda", "black"); // Calling the 2nd constructor
Transport cycle("roadways"); //Calling the 3rd constructor
cout<<"Car has "<<car.wheels<<" wheels\n";
cout<<"Name of the bike is "<<bike.name<<" and its color is "<<bike.color<<"\n";
cout<<"Cycle is a "<<cycle.type<<" mode of transportation";
return 0;
}
Output:
Copy Constructors:
A special type of constructor that can be used for directly creating a copy of an existing object of a class. To be precise, it initializes the member variables of the new object with the values of the member variables of the existing object that is being copied. The syntaxes for defining and calling the copy constructors have been given below:
Syntax:
//Definition
ClassName objectName (ClassName &existingObject)
{
Var1 = existingObject.Var1;
Var2 = existingObject.Va2;
}
//Calling
ClassName ob1;
ClassName ob2(&ob1);
Example:
#include <iostream>
using namespace std;
class Transport
{
public:
int wheels;
string name;
string color;
string type;
Transport(int n)
{
wheels=n;
}
Transport(Transport &ob) //Defining a copy constructor
{
wheels=ob.wheels;
}
};
int main()
{
Transport car1(4); // Calling the 1st constructor
Transport car2(car1); //Method1 of calling a copy constructor
Transport car3=car2; //Method2 of calling a copy constructor
cout<<"Car2 has "<<car2.wheels<<" wheels\n";
cout<<"Car3 has "<<car3.wheels<<" wheels";
return 0;
}
Output:
Default Constructor
It is possible that some constructors might not have any arguments at all. Such types of constructors are called default constructors. In the scenarios where no user-defined constructor exists for a class and one is needed, the compiler makes an implicit declaration of an inline default constructor that does not have any parameters. These constructors do not have any constructor initializer or body.
Syntax:
class ClassName {
//member variables
//member functions
};
int main()
{
ClassName object; //Calling of default constructor
….
….
return 0;
}
Example:
#include <iostream>
using namespace std;
class Book
{
public:
int isbn;
string title;
string author;
string type;
};
int main()
{
Book B1;
//Default Constructor has been created implicitly
cout<<"Success!";
return 0;
}
Output:
NOTE: Every default constructor can be treated as zero argument constructor, but every zero argument constructor cannot be called a default constructor.
Constructor with Default Arguments
A constructor that holds default values for its parameters is known as a constructor with default arguments. The calling of a constructor with default arguments can be done with either one argument or no argument at all. The parameters of a constructor may or may not have default arguments. You can skip passing the values for the variable members with default values while creating the object. It becomes mandatory to pass the values for the variable members when calling a constructor of the class that has arguments without default values. Take a look at its syntax given below:
Syntax:
class ClassName(){
type variable1;
type variable2;
….
….
ClassName(type argument1=value1, type argument2=value2, ….) //Constructor definition
{
variable1=argument1;
variable2=argument2;
….
….
}
….
//Other member functions
….
};
Example:
#include <iostream>
using namespace std;
class Book
{
public:
int isbn;
string title;
string author;
string type;
// Constructor with default arguments
Book(int n=1244, string name="Sally's Nightmare", string writer="M.Jose", string category="Fiction")
{
isbn = n;
title=name;
author=writer;
type=category;
}
};
int main()
{
Book B1(15467, "The Picture of Dorian Gray", "Oscar Wilde", "Fiction");
Book B2; //1
cout<<"Details of first book:\n"<< B1.isbn << endl<< B1.title<< endl<< B1.author<< endl<< B1.type<< endl;
cout<<"\nDetails of second book: \n"<< B2.isbn<< endl<< B2.title<< endl<< B2.author<< endl<< B2.type;
return 0;
}
In line 1, no parameter has been passed while creating the B2 object. Hence, the calling of default constructor leads to assigning the default values to the member variables of the object B2.
Output
Uses of Copy Constructor
- When we initialize an object by another object of the same class.
- When we return an object as a function value.
- When the object is passed to a function as a non-reference parameter.
Example of Copy Constructor in C++
#include <iostream>
using namespace std;
class ABC
{
public: int x;
ABC (int a){ // this is parameterized constructor
x=a;
}
ABC (ABC &i){ // this is copy constructor
x = i.x;
}
};
int main ()
{
ABC a1(40); // Calling the parameterized constructor.
ABC a2(a1); // Calling the copy constructor.
cout<<a2.x;
return 0;
}
Output:
In the above example, we are using both parameterised constructor and copy constructor. The variable ‘i’ is the object which stores the copy of variable ‘x’.
Constructor Copies
There are two ways in which copy constructor copies, and they are:
- Shallow copy.
- Deep copy.
Let’s go through these topics one by one.
Shallow Copy
- It is the process of creating a copy of an object by copying data of all the member variables as it is.
- Only a default Constructor produces a shallow copy.
- A Default Constructor is a constructor which has no arguments.
Let us understand deeply how it works through programming example
#include <iostream>
using namespace std;
class Opp {
int a;
int b;
int *z;
public: Opp() {
z=new int;
}
void input(int x, int y, int l) {
a=x;
b=y;
*z=l;
}
void display() {
cout<<"value of a:" <<a<<endl;
cout<<"value of b:" <<b<<endl;
cout<<"value of z:" <<*z<<endl;
}
};
int main() {
Opp obj1;
obj1.input(4,8,12);
Opp obj2 = obj1;
obj2.display();
return 0;
}
Output:
Explanation for above one is given in figure below:
obj1 Shallow copy obj 2
A B C
4
8
2
12
x y
z
Fig: illustration of shallow copy
- In the above figure, both ‘obj1’ and ‘obj2’ will be having the same input and both the object variables will be pointing to the same memory locations.
- The changes made to one object will affect another one.
- This particular problem is solved by using the user-defined constructor, which uses deep copy.
Deep Copy
- It dynamically allocates memory for the copy first and then copies the actual value.
- In a deep copy, both objects which have to copy and another which has to be copied will be having different memory locations.
- So, the changes made to one will not affect another.
- This is used by a user-defined copy constructor.
The syntax for the user-defined copy constructor is mentioned above refer to that. Let us see the example for the same below
#include<iostream>
using namespace std;
class Number {
private: int a;
public: Number(){} //default constructor Number (int n) {
Number(int n){
a=n;
}
Number(Number &x) {
a=x.a;
cout<<"copy constructor is invoked";
}
void display() {
cout<<"value of a:"<<a<<endl;
}
};
int main() {
Number N1(100); // create an object and assign value to member variable
Number N2(N1); // invoke user defined copy constructor
N1.display ();
N2.display ();
return 0;
}
Output:
N1 N2
n 100 x100
➢ In the above example, N1 and N2 are the two objects. ‘N2’ is the object which stores the value of objec’N1’. ‘N1’ takes 100 as input and will initialise to ‘N2’. ➢ Both N1 and N2 will have different locations.
➢ Changes made to one will not affect the other.
Difference between Copy Constructor and Assignment Operator
Copy Constructor | Assignment Operator |
It is an overloaded constructor. | It is an operator. |
The new object is initialized with an object already existing. | Value of one object is assigned to another object both of which exists already. |
Here, both the objects use different or separate memory locations. | Here, different variables points to the same location but only one memory location is used. |
The compiler provides a copy constructor if there is no copy constructor defined in the class. | Bitwise copy will be made if the assignment operator is not overloaded. |
Copy Constructor is used when a new object is being created with the help of the already existing element. | Assignment operator is used when we need to assign an existing object to a new object |
Let us now look at the differences between assignment and initialisation.
Consider the following code segment:
MYClass a;
MYClass b=a;
➢ Here, the variable b is initialized to a because it is created as a copy of another variable. When b is created, it will go from containing garbage data directly to holding a copy of the value of a with no intermediate step.
However, if we re-write the code as
MYClass a, b;
b=a;
➢ Then two is assigned the value of one. Note that before we reach the line b=a, B already contains a value. This is the difference between assignment and initialisation. When a variable is created is set to hold a new value, it is being assigned.
Note:
We can make the copy constructor private, but when we make the constructor private, that class’s objects cannot be copied. This is useful when our class has pointer variables or dynamically allocated resources. In such a situation, we can either write our copy constructor or make a private copy constructor so that the user gets compiler errors rather than something at runtime.
This brings us to the end of the blog on Copy Constructor in C++. We hope that you were able to gain some knowledge from the same. If you wish to learn more such concepts about constructor in C++ or any other programming languages, you can join Great Learning Academy’s Free Online Courses today.
Also, if you are preparing for Interviews, check out these Interview Questions for C++ to ace it like a pro.