Open In App

How to Implement a Copy Constructor for Deep Copying?

Last Updated : 27 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

In C++, the copy constructor enables us to initialize an object using another object of the same class. In this article, we will learn, how to implement a copy constructor for deep copying.

Implementing a Copy Constructor for Deep Copying

In C++, a copy constructor is used to create a copy of an object from an existing object of the same class. By default, the compiler-generated copy constructor creates a shallow copy which means if the object contains pointers to dynamically allocated memory, both the original and the copied objects will point to the same memory location so the changes made through one object’s pointer will affect the other object, which might lead to unintended behavior or errors.

To ensure each object has its own independent copy of dynamically allocated memory, we can explicitly define a deep copy constructor that allocates separate memory for the copied object’s pointers, thus ensuring changes in one object do not affect the other.

C++ Program to Implement a Copy Constructor for Deep Copying

The below example implements a copy constructor to create a deep copy of an object that has a character array as a data member.

C++
// C++ Program that illustrates the Implementation of Copy
// Constructor for Deep Copying
#include <cstring>
#include <iostream>
using namespace std;

class Student {
public:
    int roll;
    char* name;
    Student(int roll)
        : roll(roll)
    {
        name = new char[100]; // Allocate memory for name
    }

    void setName(const char* name)
    {
        strcpy(this->name, name);
    }

    // Implementing a deep copy constructor
    Student(const Student& other)
        : roll(other.roll)
    {
        name = new char[strlen(other.name) + 1];
        strcpy(name, other.name);
    }

    // Implementing the copy assignment operator for deep
    // copying
    Student& operator=(const Student& other)
    {
        if (this != &other) { // Prevent self-assignment
            roll = other.roll;
            delete[] name; // Free existing name memory
            name = new char[strlen(other.name) + 1];
            strcpy(name, other.name);
        }
        return *this;
    }

    // Implementing a destructor to deallocate dynamically
    // allocated memory
    ~Student() { delete[] name; }
};

int main()
{
    // Create an object
    Student s1(100);
    s1.setName("John");
    cout << "Original Object: " << s1.name << endl;

    // Creating a copy of the object s1
    Student s2 = s1; // Use copy constructor
    cout << "Copy Object: " << s2.name << endl;

    // Making changes in the data member of the copy object
    s2.name[0] = 'S';

    // Printing data members of both objects after making
    // changes in copy object
    cout << "After Changes:" << endl;
    cout << "Original Object: " << s1.name << endl;
    cout << "Copy Object: " << s2.name << endl;

    return 0;
}

Output
Original Object: John
Copy Object: John
After Changes:
Original Object: John
Copy Object: Sohn

Time Complexity: O(N), here N denotes the size of the dynamic object.
Auxiliary Space: O(N)





Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads