Understanding and Practicing Assignment Operator Overloading in C++

Introduction

In C++ programming, assignment operator overloading is a very important and fundamental concept. It plays a key role in handling assignment operations between class objects, especially when the class contains properties that point to heap memory. Today, we will delve into the assignment operator overloading in C++.

Functions Automatically Added by the C++ Compiler

The C++ compiler will add at least four functions to a class if no user-defined ones are provided:

  1. Default Constructor: No parameters, with an empty function body. It is mainly used for some default initialization operations when creating an object. If the user does not explicitly define a constructor, the compiler will provide this default constructor.
  2. Default Destructor: Also has no parameters and an empty function body. The destructor is called when the object’s lifecycle ends, used to release the resources occupied by the object. The default destructor can meet basic needs in most cases, but when the object contains dynamically allocated resources, we need to define a custom destructor to properly release those resources.
  3. Default Copy Constructor: It performs a value copy of the class’s properties. When we use an existing object to initialize a new object, the copy constructor is called. The default copy constructor works well for properties of basic data types, but for pointer-type properties that point to heap memory, it may lead to shallow copy issues.
  4. Assignment Operator operator=: Used for assignment operations on class objects, which by default only performs value copying of properties.

Shallow and Deep Copy Issues When Class Properties Point to Heap Memory

When a class has properties that point to heap memory, shallow and deep copy issues arise during assignment operations. Shallow copy simply copies the pointer’s value, meaning that the pointers of two objects will point to the same block of heap memory. When one of the objects is destroyed, this memory is released, and the pointer of the other object becomes a dangling pointer, leading to program errors.

To solve this problem, we need to perform a deep copy. A deep copy reallocates a block of memory on the heap and copies the data from the heap memory pointed to by the source object into the newly allocated memory, ensuring that both objects have independent heap memory spaces and do not affect each other.

Example of Assignment Operator Overloading

Let’s look at a specific example code:

class Person{public:    Person(int age)    {        // Allocate age data on the heap        m_Age = new int(age);    }    // Overload assignment operator     Person& operator=(Person &p)    {        if (m_Age != NULL)        {            delete m_Age;            m_Age = NULL;        }        // The compiler-provided code is shallow copy        //m_Age = p.m_Age;        // Provide deep copy to solve shallow copy issue        m_Age = new int(*p.m_Age);        // Return itself        return *this;    }    ~Person()    {        if (m_Age != NULL)        {            delete m_Age;            m_Age = NULL;        }    }    // Pointer for age    int *m_Age;};void test01(){    Person p1(18);    Person p2(20);    Person p3(30);    p3 = p2 = p1; // Assignment operation    cout << "p1's age is:" << *p1.m_Age << endl;    cout << "p2's age is:" << *p2.m_Age << endl;    cout << "p3's age is:" << *p3.m_Age << endl;}int main() {    test01();    //int a = 10;    //int b = 20;    //int c = 30;    //c = b = a;    //cout << "a = " << a << endl;    //cout << "b = " << b << endl;    //cout << "c = " << c << endl;    system("pause");    return 0;}

In this example, the <span>Person</span> class has a pointer of type <span>int</span> that points to the heap to store age. By overloading the assignment operator <span>operator=</span>, we achieve deep copy. In the overloaded function, we first check if our own <span>m_Age</span> is already pointing to heap memory; if so, we release it first, then reallocate memory on the heap and copy the age value from the source object. Finally, we return ourselves, allowing for chained assignment operations like <span>p3 = p2 = p1</span>.

This example illustrates the importance of assignment operator overloading when handling assignments of class objects, and how to avoid the issues caused by shallow copies through deep copies. In actual C++ programming, when our class contains dynamically allocated resources, we must remember to correctly overload the assignment operator to ensure the correctness and stability of the program.

Follow our public account to learn more knowledge

Send 【python】 to getPython learning materials

Leave a Comment