ProgrammingC++ Developer

What are the differences between shallow copy and deep copy in C++? In which situations should deep copying be implemented manually, and how can this be done correctly?

Pass interviews with Hintsage AI assistant

Answer.

Shallow copy – copies only the values of the object's fields, including pointers, but does not duplicate dynamically allocated memory. As a result, both objects point to the same memory area. This can lead to errors when modifying data or freeing memory.

Deep copy – creates a full copy of all resources that the object points to, so that each object owns its own copy of the data.

When deep copy is needed:

  • When the object owns dynamically allocated memory.
  • When modifying the contents of one object should not affect another.

Example of deep copy implementation:

class ArrayHolder { public: ArrayHolder(size_t size) : sz(size), data(new int[size]) {} ~ArrayHolder() { delete[] data; } // Deep copy constructor ArrayHolder(const ArrayHolder& other) : sz(other.sz), data(new int[other.sz]) { std::copy(other.data, other.data + other.sz, data); } // Deep copy assignment ArrayHolder& operator=(const ArrayHolder& other) { if (this != &other) { delete[] data; sz = other.sz; data = new int[sz]; std::copy(other.data, other.data + sz, data); } return *this; } private: size_t sz; int* data; };

Trick question.

Question: Will the copy constructor work correctly if it simply copies the pointer value?

Answer: No, this will lead to double deletion of memory when both objects are destroyed. Deep copying must be implemented for proper resource management.

Examples of real errors due to misunderstanding of the topic.


Story

In one of the projects, to pass arrays between modules, class objects were used where the default copy constructor copied only the pointer (shallow copy). As a result, after the temporary object went out of scope, the array was destroyed, while the main object was left with a "dangling" pointer, leading to undefined behavior and application crashes.


Story

In a library for working with images, objects containing dynamically allocated buffers were repeatedly copied. Due to the absence of deep copy, after freeing memory in one object, another accessed the freed area. This led to both data corruption and crashes when deleting the object.


Story

When integrating legacy code with modern standards, old classes did not have either the copy constructor or assignment operator implemented. Using these classes with standard library containers led to unexpected failures, as the containers copied objects shallowly.