Shallow copy vs. deep copy in C++

Copying is a typical procedure when working with objects or data structures in programming languages such as C++. It's essential to know the differences between shallow copy and deep copy to manage memory and ensure accurate data duplication.

Difference between shallow and deep copy
Difference between shallow and deep copy

Shallow copy

Shallow copies are those in which the contents of an object are not replicated. Instead, only the top-level structure is replicated.

Characteristics of a shallow copy

  • The values of any pointers, references, or data members from the source object are copied.

  • A shallow copy creates a new object but does not duplicate the dynamically allocated memory. The original and the copied object share the same memory addresses for dynamically allocated data.

  • The duplicated object's pointers may still point to the same memory locations as the original one did, depending on the implementation, but it does not universally guarantee this behavior.

Example of shallow copy

Let’s look at an example of how shallow copy works:

#include <iostream>
using namespace std;
class ShallowCopy
{
private:
int *data;
public:
ShallowCopy()
{
delete data;
}
ShallowCopy(int val)
{
data = new int(val);
}
ShallowCopy(const ShallowCopy &obj)
{
data = obj.data;
}
void displayData()
{
cout << "Data: " << *data << endl;
}
};
int main()
{
ShallowCopy org(19);
ShallowCopy shallowCopy = org;
org.displayData();
shallowCopy.displayData();
return 0;
}

Code explanation

  • Line 4: We define a class named ShallowCopy.

  • Lines 6–7: We use the access specifier to specify that the data member is private and cannot be accessed directly outside the class.

  • Lines 11–14: We define the destructor for the ShallowCopy class.

  • Lines 16–19: We define a constructor that initializes data by dynamically allocating memory for an integer and storing the value val in it.

  • Lines 22–25: We define a copy constructor that performs a shallow copy by assigning the data pointer of the new object to the data pointer of the copied object.

  • Lines 27–30: We define a function displayData() that displays the value pointed to by data.

  • Line 35: We create an object org of the ShallowCopy class, passing 19 as the initial value.

  • Line 36: We make a shallow copy of the org object and assigns it to shallowCopy.

  • Line 37: We call the displayData() function for the original object, displaying the data stored in it.

  • Line 38: We call the displayData() function for the shallowCopy object, displaying the same data as the original object.

Note: The use of an ampersand in a copy constructor allows for the passing of the object by reference rather than by value. This means that instead of creating a new object and copying the data from the original object, the copy constructor receives a reference to the original object. This can improve performance and efficiency, especially when dealing with large objects.

Deep copy

In a deep copy, the top-level structure is copied together with the contents, including dynamically produced memory.

Characteristics of a deep copy

  • It involves duplicating all the elements, including recursively copying any objects or data structures within the object.

  • Each copied object has its own unique memory space, independent of the original.

Example of deep copy

Let’s look at an example of how deep copy works:

#include <iostream>
using namespace std;
class DeepCopy
{
private:
int *data;
public:
DeepCopy()
{
delete data;
}
DeepCopy(int val)
{
data = new int(val);
}
DeepCopy(const DeepCopy &obj)
{
data = new int(*(obj.data));
}
void displayData()
{
cout << "Data: " << *data << endl;
}
};
int main()
{
DeepCopy original(19);
DeepCopy deepCopy = original;
original.displayData();
deepCopy.displayData();
return 0;
}

Code explanation

  • Line 4: We define a class named DeepCopy.

  • Lines 6–7: We use the access specifier to specify that the data member is private and cannot be accessed directly outside the class.

  • Lines 11–14: We define the destructor for the DeepCopy class.

  • Lines 16–19: We define a constructor that initializes data by dynamically allocating memory for an integer and storing the value val in it.

  • Lines 22–25: We define a copy constructor to ensure that when a new DeepCopy object is created by copying another DeepCopy object, it allocates new memory for its data member and copies the value of the data from the source object. This results in a deep copy where the objects have separate memory locations for their data and modifications to one object's data do not affect the other.

  • Lines 27–30: We define a function displayData() that displays the value pointed to by data.

Free Resources

Copyright ©2024 Educative, Inc. All rights reserved