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.
Shallow copies are those in which the contents of an object are not replicated. Instead, only the top-level structure is replicated.
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.
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;}
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.
In a deep copy, the top-level structure is copied together with the contents, including dynamically produced memory.
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.
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;}
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