C++ Assignment Operator Overloading: Handling Deep and Shallow Copy Issues

When you define a class in C++, the compiler automatically provides four special member functions: - Default constructor (no parameters, empty body)

  • Default destructor (no parameters, empty body)
  • Default copy constructor (performs value copy of member variables)
  • Assignment operator operator= (performs value copy of member variables)

Problem Description

When a class contains members that point to heap-allocated memory, performing assignment operations can introduce deep and shallow copy porblems. Consider this example: ``` class Person { public: Person(int age) { // Allocate age data on the heap m_Age = new int(age); }

// Pointer to age
int *m_Age;

};


### Solution

The assignment operator can be overloaded to properly handle deep copying: ```
class Employee
{
public:

    Employee(int salary)
    {
        // Allocate salary data on the heap
        m_Salary = new int(salary);
    }

    // Overload assignment operator
    Employee& operator=(Employee& emp)
    // Cannot return void; enables chained assignment like a=b=c
    {
        // Check if current object already has heap memory, release it first before deep copy
        if (m_Salary != NULL)
        {
            delete m_Salary;
            m_Salary = NULL;
        }
        
        // Compiler-provided code performs shallow copy
        // m_Salary = emp.m_Salary;

        // Implement deep copy to resolve shallow copy issue
        m_Salary = new int(*emp.m_Salary);

        // Return reference to this object
        return *this;
    }


    ~Employee()
    {
        if (m_Salary != NULL)
        {
            delete m_Salary;
            m_Salary = NULL;
        }
    }

    // Salary pointer
    int *m_Salary;

};


void testAssignment()
{
    Employee emp1(5000);
    Employee emp2(7000);
    Employee emp3(9000);

    emp3 = emp2 = emp1; // Chained assignment operation

    cout << "Employee 1 salary: " << *emp1.m_Salary << endl;
    cout << "Employee 2 salary: " << *emp2.m_Salary << endl;
    cout << "Employee 3 salary: " << *emp3.m_Salary << endl;
}

int main() {
    testAssignment();
    return 0;
}

Summary

Both copy constructors and assignment operator overloading can resolve deep and shallow copy problems. The distinction lies in when they are invoked: the copy constructor is called during object initialization (e.g., Person p2 = p1;), while the assignment operator is called when assigning to an already-constructed object (e.g., p2 = p1;).

Posted on Tue, 12 May 2026 18:42:08 +0000 by JonathanAnon