Copy assignment function of [C + +] class

Posted by fuzzy1 on Sun, 27 Feb 2022 09:38:25 +0100

Reprint [to] C + + assignment constructor (assignment operator overload)

Note: the content of the article is not strictly verified. Please leave a message if you have any questions or errors.

When an object of a class assigns a value to another object of the class, the assignment constructor of the class will be used. When the assignment constructor (assignment operator) is not overloaded, the assignment operation is carried out through the default assignment constructor.

A a;
A b;
b = a;

Note: here, a and b objects already exist and are assigned to b by a object.

The overload declaration of the assignment operator is as follows:

A& operator = (const A& other)

Generally, people will confuse the copy constructor with the assignment constructor. Here, carefully compare the differences between the two:

1) The copy constructor initializes a memory area of an object, which is the memory area of a new object. When assigning a constructor, it assigns a value to an object that has been initialized.

class  A;
A a;
A b=a;   //Call copy constructor (b does not exist)
A c(a) ;   //Call copy constructor

/****/

class  A;
A a;
A b;
b = a ;   //Call assignment function (b exists)

2) The implementation is different. The copy constructor is first a constructor, which generates a new object through the object initialization of parameters. Assignment constructor is to assign a new object to an original object.

give an example:

#include<iostream>
#include<string>
using namespace std;

class MyStr
{
private:
    char *name;
    int id;
public:
    MyStr():id(0),name(NULL) {}
    MyStr(int _id, char *_name)   //Constructor
    {
        cout << "constructor" << endl;
        id = _id;
        name = new char[strlen(_name) + 1];
        strcpy_s(name, strlen(_name) + 1, _name);
    }
    MyStr(const MyStr& str)    //copy constructor 
    {
        cout << "copy constructor" << endl;
        id = str.id;
        name = new char[strlen(str.name) + 1];
        strcpy_s(name, strlen(str.name) + 1, str.name);
    }
    MyStr& operator =(const MyStr& str)//Assignment Operators 
    {
        cout << "operator =" << endl;
        if (this != &str)
        {
            if (name != NULL)
                delete[] name;
            this->id = str.id;
            int len = strlen(str.name);
            name = new char[len + 1];
            strcpy_s(name, strlen(str.name) + 1, str.name);
        }
        return *this;
    }
    ~MyStr()
    {
        delete[] name;
    }
};

int main()
{
    MyStr str1(1, "hhxx");
    cout << "====================" << endl;
    MyStr str2;
    str2 = str1;
    cout << "====================" << endl;
    MyStr str3 = str2;
    return 0;
}

result:

explain:

1. Parameters

Generally, the parameter of the overloaded function of the assignment operator is the reference of the const type of the class where the function is located. Const is added because:

(1) We don't want to make any changes to the "original" used for assignment in this function.

(2) With const, functions can accept const and non const arguments; If not, only non const arguments can be accepted.

Reference is used because:

This can avoid one copy of the arguments during function call and improve the efficiency.

Note: the above provisions are not mandatory. const or no reference can be added.

2. Return value

Generally, the return value is the reference of the assignee, i.e. * this (as in example 1 above). The reason is:

(1) This avoids one copy when the function returns and improves the efficiency.

(2) More importantly, this can realize continuous assignment, that is, similar to a=b=c. If you return the value type instead of the reference, when a=b is executed, call the assignment operator to overload the function. When the function returns, because it returns the value type, you need to copy the "thing" behind the return to get an unnamed copy (some materials call it "anonymous object"), and then return this copy, This copy is an R-value, so after executing a=b, you get an R-value, and then executing = c will make an error.

Note: This is not mandatory. We can even declare the return value of the function as void and return nothing, but we can't assign values continuously

3. Assignment operator overloaded functions cannot be inherited

Compared with the base class, the derived class often needs to add its own data members and member functions. If the derived class is allowed to inherit the accumulated assignment operator overloaded functions, when the derived class does not provide its own assignment operator overloaded functions, it can only call the of the base class, but the base class version can only process the data members of the base class. In this case, What about the derived class's own data members? Therefore, C + + stipulates that overloaded functions of assignment operators cannot be inherited.

4. Assignment operators overload functions to avoid self assignment

For overloaded functions of assignment operators, we should avoid the occurrence of self assignment (i.e. self assignment). Generally, we judge whether they are the same object by comparing whether the addresses of the assignor and the assignee are the same (such as if (this! = & STR) in the example). The meaning of avoiding self assignment is:

(1) To improve efficiency, it is obviously meaningless and useless to assign values to yourself. In particular, for the assignment between data members of the base class, the assignment operator of the base class will be called to overload the function, which is very expensive. If we decide that it is self assignment, we will immediately return *this to avoid calling other functions.

(2) If the data members of a class contain pointers, self assignment can sometimes lead to disastrous consequences. For the assignment between pointers (note that this refers to the assignment between the contents of the pointer. Here, it is assumed that _pis used to assign a value to P), first delete the space pointed to by P (why do you do this? Because the space pointed to by pointer P is usually new. If the original space of P is not deleted before reallocating space for P, memory leakage will be caused), Then reallocate space for P, and_ Copy the content indicated by P to the space indicated by P. If it is self assignment, then p and_ P is the same pointer. The delete operation on P before the assignment operation will cause the data referred to by P to be destroyed at the same time. So what do you assign when you reassign?

Therefore, for the overloaded function of assignment operator, you must first check whether it is self assignment. If so, return *this directly.

Reprinted from:

<Difference and implementation of constructor, copy constructor and assignment function in C + +>

<This article describes the overloaded function of C + + assignment operator (operator =)>

Topics: C++ C++11