Shallow Copy Vs Deep Copy

Shallow Copy Vs Deep Copy

Understanding the concepts through examples.

Both the copy methods are used to copy one object to another object of the same class i.e. to make a replica of the object of the same class. Member variables of the object of the class are copied to another object of the same class.

1. Shallow Copy

In shallow copy, an object is created by simply copying the data of all variables of the original object. This works well if none of the variables of the object is defined in the heap section of the memory. If some variables are dynamically allocated in the heap section, then the copied object variable will also reference the same memory location. So if one object changes that variable value, the changed value will also be reflected in another object. Let's learn through examples.

#include<iostream>
using namespace std;

class A{
  int *a;
  public:
    A(){
      a = new int(5); //created in heap memory
    } 
    void changeValueof_a(){
      *a = 10;
    }
};

int main() {
  A obj1;
  A obj2 = obj1; //default copy constructor called
  obj2.changeValueof_a(); //the changed value will also be reflected in obj1
  return 0;
}

In the above example class 'A' has two objects, 'obj1' & 'obj2'. Object 'obj1' sets the value of 'a' to 5 through default constructor. This value is copied to Object 'obj2' through default copy constructor. Now both the objects have variable 'a' set to 5 and it is shared between both the objects as it is in heap memory section. Check the below image.

Now when the object 'obj2' changes the value of 'a' through method 'changeValueof_a()' it will also be reflected in object 'obj1' because the memory is shared.

This causes problems because we don't want the variable to be changed in object 'obj1'. This is called shallow copy. The default constructor does only shallow copy. To resolve this issue we use deep copy of objects.

2. Deep Copy

In deep copy, an object is created by copying data of all variables, and it also allocates similar memory resources with the same value to the object. To perform deep copy, we need to explicitly define the copy constructor and assign dynamic memory as well. The above code is modified as below.

#include<iostream>
using namespace std;

class A{
  int *a;
  public:
    A(){
      a = new int(5); //created in heap memory
    }

    //user defined copy constructor
    A(A &obj){
      a = new int(*obj.a); //allocate dynamic memory here also
    }

    void changeValueof_a(){
      *a = 10;
    }
};

int main() {
  A obj1;
  A obj2 = obj1; //user defined copy constructor called
  obj2.changeValueof_a(); //the changed value will not be reflected in obj1
  return 0;
}

Now, we have created a user-defined copy constructor where we are changing the value of 'a' by allocating dynamic memory as well. Now, the memory structure looks like the one below.

Now when the object 'obj2' changes the value of 'a' through method 'changeValueof_a()', it will not be reflected in object 'obj1' because the memory is not shared.

Deep copy is possible only with a user-defined copy constructor.

So, In general, if the variables of an object have been dynamically allocated, then it is required to do a Deep Copy to create a copy of the object.