The mechanics of copying objects in C++ is divided into shallow copy and deep copy. The difference is particularly important for classes with dynamically allocated memory.
In C++, many data structures work with dynamic memory (new/delete). By default, the compiler generates a copy constructor and assignment operator that performs a byte-for-byte copy (shallow copy). This is fast but dangerous if the object manages external resources.
Shallow copy copies only the addresses of dynamically allocated resources. When deleting one object, the memory will be freed, leaving the other instance with a "dangling" pointer. This results in double deletes, memory leaks, and crashes.
Deep copying involves explicitly creating copies of all dynamic resources. To do this, the class must implement its own copy constructor and assignment operator to ensure a copy of each element.
Example code for a class with an array:
class DynArray { int* data; size_t size; public: DynArray(size_t n) : size(n), data(new int[n]) {} ~DynArray() { delete[] data; } // Deep copy constructor DynArray(const DynArray& other) : size(other.size), data(new int[other.size]) { for (size_t i = 0; i < size; ++i) data[i] = other.data[i]; } // Deep copy assignment DynArray& operator=(const DynArray& other) { if (this != &other) { delete[] data; size = other.size; data = new int[size]; for (size_t i = 0; i < size; ++i) data[i] = other.data[i]; } return *this; } };
Key features:
The compiler always correctly generates a copy constructor and assignment operator, right?
Answer:
Incorrect. For classes with dynamic resources, default copying is incorrect: both objects will own the same resource. Deep copy must be explicitly implemented when owning external resources.
Is it necessary to implement a destructor if only the deep copy constructor/assignment is written?
Answer:
Yes, otherwise there will be a memory leak: if you free memory in the user-defined copy constructor but do not implement a destructor, memory will not be freed when objects are destroyed.
Can std::vector store pointers and why can there be leaks when copying it?
Answer:
Yes, std::vector can store pointers. When copying such a std::vector, the pointers themselves are copied, not the objects they point to. This is shallow copy: if you need to deep copy all contents, you will need to manually copy each object and place them in memory independently.
Example:
std::vector<int*> v1; v1.push_back(new int(42)); std::vector<int*> v2 = v1; // Pointers are copied, not *int
A programmer implements a wrapper class for an array without overriding the copy constructor/assignment operator. As a result, both objects own the same memory; destroying one leads to a crash when accessing the other.
Pros:
Cons:
A developer implements deep copying: contents of the array are copied, there is its own destructor and assignment operator with self-assignment protection.
Pros:
Cons: