Copy Constructor in C++

Copy Constructor

Here, in this section, we will discuss the copy constructor in C++. Copy Constructor in C++is a type wherein we use an existing object to create multiple construction initializations for newer objects that will be created. It is a special member function of the class.

copy constructor in C++

What is a Copy Constructor?

class_name (class-name &){
     ....
}
  • 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.
  • The compiler provides a default Copy Constructor to all the classes.

Code

Run
#include<iostream>
using namespace std;
class PrepInsta 
{ 
private: 
    int x, y; 
public: 
    PrepInsta()
    { // empty default constuctor
    }
    
    PrepInsta(int x1, int y1) 
    { 
        x = x1; 
        y = y1;

        cout << "Parameterized constructor called here" << endl;

    } 

    // User defined Copy constructor 
    PrepInsta(const PrepInsta &p2) 
    {
        x = p2.x; 
        y = p2.y; 
        cout << "Copy constructor called here" << endl;
    } 

    int getX()            
    {  
        return x; 

    } 
    int getY()            
    {  
        return y; 

    } 
}; 

int main() 
{ 
    // Trying to call parameterized constructor here
    PrepInsta p1(10, 15); 
    
    // Trying to call copy constructor here 
    PrepInsta p2 = p1; 
    
    // Trying to call Copy constructor here (Another way of doing so)
    PrepInsta p3(p1);
    PrepInsta p4;
 
    // Here there is no copy constructor called only assignment operator happens
    p4 = p1;
    
    cout << "\nFor p4 no copy constructor called only assignment operation happens\n" << endl;

    // displaying values for both constructors 
    cout << "p1.x = " << p1.getX() << ", p1.y = " << p1.getY();
    cout << "\np2.x = " << p2.getX() << ", p2.y = " << p2.getY(); 

    cout << "\np3.x = " << p3.getX() << ", p3.y = " << p3.getY(); 
    cout << "\np4.x = " << p4.getX() << ", p4.y = " << p4.getY();
    
    return 0; 
}

Output

Parameterized constructor called here
Copy constructor called here
Copy constructor called here
For p4 no copy constructor called only assignment operation happens p1.x = 10, p1.y = 15 p2.x = 10, p2.y = 15 p3.x = 10, p3.y = 15 p4.x = 10, p4.y = 15

Types of Copy Constructors

It is really great way of creating new object initialisations and is still widely used by programmers.

There are two types of copy constructors which are –

  • Default Copy Constructors (Does Shallow Copying)
  • User Defined Copy Constructors (Does Deep Copying)

We will learn more about these two in detail below –

Type of copy constructor

Shallow Copy

When we do not create our own copy constructor. C++ compiler will create a default copy constructor for each class which does a member-wise copy between objects.

This default copy constructor does shallow copy.

Copy Constructor Shallow Copy

Code

Let us see an example to see how this works –

Run
#include<iostream>
#include<string.h>
using namespace std;

class PrepInsta
{
    char *prepString;
    
    public:
    
    // Note : No user defined Copy constuctor created here
    
    PrepInsta(const char *prepString1)
    {
        //We are invoiking Dynamic memory allocation here
        prepString = new char[16]; 
        strcpy(prepString, prepString1);
    }
  
    /* concatenate method */
    void concatenate(const char *prepString1)
    {
        // using function to Concatenating two strings
        strcat(prepString, prepString1); 
    }
  
    void print()
    {
        cout << prepString << endl;
    }
};

/* main function */
int main()
{
    PrepInsta obj1("Prep");
    
    //Copy constructor
    PrepInsta obj2 = obj1; 
  
    cout << "Before concatenation - " << endl;
    
    obj1.print();
    obj2.print();
    
    // obj1 is invoking concatenate()
    // but change will also be reflected in obj2 (shallow copy)
    // see more explanation in below comments
    obj1.concatenate("Insta");
  
    cout << "\nAfter concatenation - " << endl;
    
    // as we didn't create any user defined copy constructor
    // compiler created default copy constuctor in backend on its own
    // So both obj1 & obj2 variables share same memory (shallow copy)
    // any change in obj1 also reflects in obj2
    obj1.print();
    obj2.print();

  
    return 0;
}

Output

Before concatenation - 
Prep
Prep
After concatenation - PrepInsta PrepInsta Any change in obj1 also reflects in obj2 (shallow copy)

Deep Copy

When we create our own user-defined copy constructor. The individual copies of memory are created for each object and thus there is no sharing of memory.

This user-defined copy constructor does Deep copy.

Code

Let us see an example to see how this works –

Run
#include<iostream>
#include<string.h>
using namespace std;

class PrepInsta
{
    char *prepString;
    
    public:
    PrepInsta (const char *str)
    {
        //We are invoking Dynamic memory allocation here
        prepString = new char[16];
        strcpy(prepString, str);
   }
   
   // here we are doing the change of adding additional code
   // for user defined copy constructor (Deep Copy)
    PrepInsta (const PrepInsta &x2)
    {
        //We are invoking Dynamic memory allocation here
        prepString = new char[16]; 
        strcpy(prepString, x2.prepString);
    }
   
    void concatenate(const char *prepString1)
    {
        // using function to Concatenating two strings
        strcat(prepString, prepString1);
    }
   
   ~PrepInsta()
    { 
        delete [] prepString;
    }
   
   void print()
   {
        cout << prepString << endl;
   }
};

/* main function */
int main()
{
    PrepInsta p1("Prep");
    PrepInsta p2 = p1; //copy constructor
   
   cout << "Before concatenation - " << endl;
    
    p1.print();
    p2.print();
   
    p1.concatenate("Insta");
   
    cout << "\nAfter concatenation - " << endl;
   
    p1.print();
    p2.print(); 
   
    return 0;
}

Output

Before concatenation - 
Prep
Prep
After concatenation – PrepInsta Prep Changing obj1 doesn’t reflect/cause any changes in obj2(Deep Copy)