A copy constructor is a special constructor in C++ that creates a new object as a copy of an existing object.
๐ Definition:
It takes a reference to another object of the same class as its parameter.
ClassName(const ClassName &obj) {
    // Copy code here
}
โ Purpose of Copy Constructor
- To create a new object with the same values as an existing one.
 - Helps in copying objects safely, especially when dealing with pointers or dynamic memory.
 - Used when:
- Passing an object by value to a function.
 - Returning an object from a function.
 - Initializing one object with another.
 
 
๐ง Example: Simple Copy Constructor
#include <iostream>
using namespace std;
class Student {
    int roll;
    string name;
public:
    // Parameterized Constructor
    Student(int r, string n) {
        roll = r;
        name = n;
    }
    // Copy Constructor
    Student(const Student &s) {
        roll = s.roll;
        name = s.name;
    }
    void display() {
        cout << "Roll No: " << roll << ", Name: " << name << endl;
    }
};
int main() {
    Student s1(101, "Alice");  // Original object
    Student s2 = s1;           // Copy constructor is called
    cout << "Original: ";
    s1.display();
    cout << "Copied: ";
    s2.display();
    return 0;
}
๐ฏ Output:
Original: Roll No: 101, Name: Alice  
Copied: Roll No: 101, Name: Alice
๐ก Key Features
| Feature | Description | 
|---|---|
| Name | Same as class name | 
| Parameter | Takes a reference to another object | 
| When Called | On object copy or passing/returning objects | 
| Implicit Version | C++ provides a default copy constructor | 
| Custom Version | Needed when deep copy is required | 
๐ง Shallow vs. Deep Copy
๐งช Shallow Copy:
- Copies memory address (pointer).
 - Both objects share the same memory.
 - Can cause issues when one object changes the shared data or deletes it.
 
๐งช Deep Copy:
- Copies actual data, not just the pointer.
 - Each object has its own copy.
 - Prevents unwanted changes and memory errors.
 
๐ Example of the Need for Deep Copy
If your class contains pointers or uses new, a custom copy constructor is necessary to create a deep copy.
class Example {
    int* data;
public:
    Example(int val) {
        data = new int(val);  // Dynamic memory
    }
    // Custom Copy Constructor for Deep Copy
    Example(const Example &obj) {
        data = new int(*obj.data);  // New memory allocation
    }
    ~Example() {
        delete data;  // Prevent memory leak
    }
};
๐งพ Summary
- A copy constructor creates a new object by copying another object.
 - Syntax: 
ClassName(const ClassName &obj) - Used for:
- Copying objects
 - Passing objects by value
 - Returning objects from functions
 
 - Use a custom copy constructor when dealing with pointers or dynamic memory.
 
