Copy Constructor & Dynamic Constructors in C++: Deep vs. Shallow Copy
1. What is a Copy Constructor? (In Simple Words)
A Copy Constructor is a constructor used to create a new object by copying the data of an existing object of the same class.
Syntax:
ClassName(const ClassName &sourceObject);
#include <iostream>
using namespace std;
class Point {
private:
int x, y;
public:
// Parameterized Constructor
Point(int xVal, int yVal) {
x = xVal;
y = yVal;
}
// COPY CONSTRUCTOR (Notice the '&' reference!)
Point(const Point &p) {
x = p.x;
y = p.y;
cout << "Copy Constructor called!" << endl;
}
void show() const {
cout << "Point: (" << x << ", " << y << ")" << endl;
}
};
int main() {
Point p1(10, 20); // Normal creation
// Creating new objects by copying p1:
Point p2 = p1; // Method 1: Assignment style
Point p3(p1); // Method 2: Direct style
p2.show(); // Prints: Point: (10, 20)
p3.show(); // Prints: Point: (10, 20)
return 0;
}
2. Why MUST We Pass the Argument by Reference (&)?
⚠️ TOP #1 EXAM & VIVA QUESTION:
Why is the copy constructor written asPoint(const Point &p)and NOTPoint(Point p)?
Let’s understand this step-by-step:
- If you pass by value (
Point p), C++ must make a copy of the incoming object to pass it into the constructor. - But how does C++ make a copy? By calling the copy constructor!
- To call that copy constructor, it must again make a copy of its argument…
- This creates an infinite recursive loop of constructor calls! The computer runs out of stack memory and crashes.
By using Pass by Reference (&p), no copy is made. C++ simply passes an alias (nickname) to the original object, breaking the infinite loop completely!
3. When is a Copy Constructor Automatically Called?
The C++ compiler automatically runs the copy constructor in 3 situations:
- When you create an object from another object:
Point p2 = p1;orPoint p2(p1);. - When an object is passed by value into a function.
- When an object is returned by value from a function.
4. The Big Problem: Shallow Copy vs. Deep Copy
If you don’t write your own copy constructor, C++ provides a default one. But the default one only does a Shallow Copy.
new, and copies the actual data over. Both objects have their own separate memory and can be safely deleted without any crash!SHALLOW COPY (Dangerous!):
[ Object A: ptr ] ──┐
▼
[ Heap Memory (Value: 42) ]
▲
[ Object B: ptr ] ──┘ (Both point to same place! Causes Double-Free crash on exit!)
DEEP COPY (Safe!):
[ Object A: ptr ] ──▶ [ Heap Memory 1 (Value: 42) ]
[ Object B: ptr ] ──▶ [ Heap Memory 2 (Value: 42) ] (Separate independent blocks!)
5. Dynamic Constructors in C++
A Dynamic Constructor is a constructor that uses the new operator inside its body to allocate memory from the heap dynamically at runtime.
This is useful when the size of data is not known beforehand (e.g. storing a student’s full name without wasting a fixed 100-character array).
#include <iostream>
#include <cstring>
using namespace std;
class DynamicString {
private:
char *str;
int length;
public:
// 1. DYNAMIC CONSTRUCTOR (Allocates exact heap memory needed)
DynamicString(const char *s) {
length = strlen(s);
str = new char[length + 1]; // +1 for null character '\0'
strcpy(str, s);
}
// 2. USER-DEFINED COPY CONSTRUCTOR (Performs DEEP COPY)
DynamicString(const DynamicString &source) {
length = source.length;
str = new char[length + 1]; // Allocates brand-new heap memory!
strcpy(str, source.str);
}
void display() const {
cout << str << endl;
}
// DESTRUCTOR: Cleans up heap memory when object dies
~DynamicString() {
delete[] str; // Prevents memory leaks
}
};
int main() {
DynamicString name1("CampusNotes Indore");
// Deep Copy runs safely!
DynamicString name2 = name1;
name1.display();
name2.display();
return 0; // Both objects are destroyed cleanly without any double-free crash!
}
DAVV Exam Preparation Tips
Frequently Asked 5-Mark Questions:
- What is a copy constructor? Write its standard prototype.
Model Answer:- Define: A constructor used to initialize a new object using an existing object of the same class.
- Prototype:
ClassName(const ClassName &sourceObj);.
- Why must the parameter of a copy constructor be passed by reference?
Model Answer:- Passing by value requires making a copy, which calls the copy constructor again, leading to an infinite recursive loop of constructor calls and a stack overflow crash.
Frequently Asked 10-Mark Questions:
- Explain the concepts of Shallow Copy and Deep Copy in C++. Why does shallow copy cause program crashes when dynamic memory is involved? Demonstrate with a dynamic String class implementing a Deep Copy constructor.
Model Answer:- Define Shallow Copy (bitwise copying of addresses) vs Deep Copy (allocating independent heap blocks using
new). - Draw memory diagrams showing shared heap memory vs separate heap blocks.
- Explain the “Double-Free” crash when destructors run twice on the same memory address.
- Write out the complete
DynamicStringclass with dynamic constructor, deep copy constructor, and destructor~DynamicString().
- Define Shallow Copy (bitwise copying of addresses) vs Deep Copy (allocating independent heap blocks using