Understanding Deep Copy vs Shallow Copy in C++: A Beginner's Practice Guide

Introduction

When an object is copied in C++, the values of its data members are duplicated to create a new object. For classes containing only simple data types such as integers or floating-point values, the default copying behavior is usually sufficient. However, when a class allocates memory dynamically using pointers, the way objects are copied becomes extremely important.

There are two approaches to copying objects:

  • Shallow Copy

  • Deep Copy

A shallow copy duplicates the pointer values, causing multiple objects to share the same memory location. In contrast, a deep copy allocates separate memory for each object and copies the actual data, ensuring complete independence between objects.

Understanding the difference between these two approaches is essential for writing safe and reliable C++ programs that use dynamic memory allocation.

1. Shallow Copy

A shallow copy copies every data member exactly as it exists. If a class contains pointer members, only the pointer address is copied rather than the data stored at that address.

As a result, both the original object and the copied object point to the same memory location. Any modification made through one object is immediately reflected in the other. Furthermore, when both objects are destroyed, they both attempt to release the same memory, leading to a double deletion (double free) error.

Program


Explanation

The ShallowExample class contains a pointer named dataPointer, which stores dynamically allocated memory.

The constructor allocates memory on the heap and stores the supplied value. The copy constructor performs a shallow copy by copying only the pointer address instead of creating new memory.

When the object obj2 is created as a copy of obj1, both objects contain exactly the same memory address. Therefore, they share the same integer stored on the heap.

When the value is modified through obj2, the value observed through obj1 also changes because both objects reference the same memory location.

When the program terminates, both destructors execute and attempt to delete the same heap memory. This causes a double free error, making shallow copying unsafe for classes that manage dynamic memory.

2. Deep Copy

A deep copy creates an entirely separate copy of dynamically allocated data. Instead of copying the pointer address, new memory is allocated and the actual value stored in the source object is copied into this new memory.

Each object therefore owns its own independent memory, eliminating shared ownership and preventing memory management problems.

Program


Explanation

The DeepExample class also contains a dynamically allocated pointer named dataPointer.

Unlike the previous example, the copy constructor allocates a completely new memory location using the new operator. The value stored in the source object is then copied into this newly allocated memory.

Although obj1 and obj2 initially contain the same value, they now point to different memory locations. Each object owns its own copy of the data.

When the value is modified through obj2, the value stored in obj1 remains unchanged because the objects no longer share memory.

Similarly, when the program terminates, each object's destructor deletes its own memory allocation independently, avoiding double deletion and making deep copying safe for dynamically allocated resources.

Comparison Between Shallow Copy and Deep Copy

FeatureShallow CopyDeep Copy
Copy OperationCopies only the pointer address.Copies the actual data stored in memory.
Memory AllocationOriginal and copied objects share the same heap memory.Each object has its own separately allocated heap memory.
Object IndependenceObjects are dependent on the same memory location.Objects are completely independent of one another.
Default BehaviorAutomatically provided by the compiler.Must be implemented manually using a custom copy constructor.
Memory SafetyCan cause dangling pointers and double deletion errors.Safe because every object manages its own memory.

Conclusion

Shallow copy and deep copy are important concepts when working with dynamically allocated memory in C++. A shallow copy simply duplicates pointer addresses, causing multiple objects to share the same memory and potentially leading to dangling pointers, unintended data modification, and double deletion errors. A deep copy, on the other hand, allocates new memory and copies the actual data, ensuring that each object manages its own independent resources. For classes that allocate memory dynamically, implementing a custom deep copy constructor is essential for writing safe, reliable, and maintainable C++ programs.