Copy Constructor in C++

Copy Constructor is a type of constructor which is used to create a copy of an already existing object of a class type. It is usually of the form X (X&), where X is the class name.he compiler provides a default Copy Constructor to all the classes.


Syntax of Copy Constructor

Classname(const classname & objectname)
{
 . . . .
}

As it is used to create an object, hence it is called a constructor. And, it creates a new object, which is exact copy of the existing copy, hence it is called copy constructor.

copy construction of objects

Below is a sample program on Copy Constructor:

#include<iostream>
using namespace std;
class Samplecopyconstructor
{
private:
int x, y; // data members
public:
Samplecopyconstructor(int x1, int y1)
{
x = x1;
y = y1;
}
// Copy constructor
Samplecopyconstructor (const Samplecopyconstructor &sam)
{
x = sam.x;
y = sam.y;
}
void display()
{
cout<<x<<" "<<y<<endl;
}
};
int main()
{
Samplecopyconstructor obj1(10, 15); // Normal constructor
Samplecopyconstructor obj2 = obj1; // Copy constructor
cout<<"Normal constructor : ";
obj1.display();
cout<<"Copy constructor : ";
obj2.display();
return 0;
}

Output:

Normal constructor : 10 15
Copy constructor : 10 15

Shallow Copy Constructor

The concept of shallow copy constructor is explained through an example. Two students are entering their details in excel sheet simultaneously from two different machines shared over a network. Changes made by both of them will be reflected in the excel sheet. Because same excel sheet is opened in both locations. This is what happens in shallow copy constructor. Both objects will point to same memory location.

Shallow copy copies references to original objects. The compiler provides a default copy constructor. Default copy constructor provides a shallow copy as shown in below example. It is a bit-wise copy of an object.

Shallow copy constructor is used when class is not dealing with any dynamically allocated memory.

Shallow Copy Constructor

In the below example you can see both objects, c1 and c2, points to same memory location. When c1.concatenate() function is called, it affects c2 also. So both c1.display() and c2.display() will give same output.

#include<iostream>
#include<cstring>
using namespace std;
class CopyConstructor
{
char *s_copy;
public:
CopyConstructor(const char *str)
{
s_copy = new char[16]; //Dynamic memory allocation
strcpy(s_copy, str);
}
void concatenate(const char *str)
{
strcat(s_copy, str); //Concatenating two strings
}
~ CopyConstructor (){ delete [] s_copy;}
void display()
{
cout<<s_copy<<endl;
}
};
int main()
{
CopyConstructor c1("Copy");
CopyConstructor c2=c1; //Copy constructor
c1.display();
c2.display();
c1.concatenate("Constructor"); //c1 is invoking concatenate()
c1.display();
c2.display();
return 0;
}

Output:

Copy
Copy
CopyConstructor
CopyConstructor

Deep Copy Constructor

Let's consider an example for explaining deep copy constructor. You are supposed to submit an assignment tomorrow and you are running short of time, so you copied it from your friend. Now you and your friend have same assignment content, but separate copies. Therefore any modifications made in your copy of assignment will not be reflected in your friend's copy. This is what happens in deep copy constructor.

Deep copy allocates separate memory for copied information. So the source and copy are different. Any changes made in one memory location will not affect copy in the other location. When we allocate dynamic memory using pointers we need user defined copy constructor. Both objects will point to different memory locations.

Deep Copy Constructor

General requirements for deep copy:

  • A normal constructor.
  • A destructor to delete the dynamically allocated memory.
  • A copy constructor to make a copy of the dynamically allocated memory.
  • An overloaded assignment operator.

In the previous example you can see when c1 called concatenate(), changes happens in both c1 and c2, because both are pointing to same memory location.

In the below example you can see user defined copy constructor i.e deep copy constructor. Here both c1 and c2 points to different memory location. So changes made in one location will not affect the other.

#include<iostream>
#include<cstring>
using namespace std;
class CopyConstructor
{
char *s_copy;
public:
CopyConstructor (const char *str)
{
s_copy = new char[16]; //Dynamic memory alocation
strcpy(s_copy, str);
}
CopyConstructor (const CopyConstructor &str)
{
s_copy = new char[16]; //Dynamic memory alocation
strcpy(s_copy, str.s_copy);
}
void concatenate(const char *str)
{
strcat(s_copy, str); //Concatenating two strings
}
~ CopyConstructor(){ delete [] s_copy;}
void display()
{
cout<<s_copy<<endl;
}
};
int main()
{
CopyConstructor c1("Copy");
CopyConstructor c2=c1;//copy constructor
c1.display();
c2.display();
c1.concatenate("Constructor"); //c1 is invoking concatenate()
c1.display();
c2.display();
return 0;
}

Output:

Copy
Copy
CopyConstructor
Copy