Assignment operator overload
Explain
Assignment operator overload is to assign a value to another object with an existing object. After both objects have been created, assignment occurs.
grammar
Fixed format Class name { Class name & operator = (const class name & source object) Copy body } class A { A& operator=(const A& another) { / / function body return *this; } } ;
Characteristic
#include <iostream> using namespace std; struct Data { public: Data(int y = 2016, int m = 6, int d = 6) :year(y), month(m), day(d), space(new char[1024]) {} void dis() { cout << " year " << year << " month " << month << " day " << day << endl; } private: int year; int month; int day; char* space; }; int main() { Data d(2018, 8, 8); d.dis(); Data d2(2019, 9, 9); d2 = d; d2.dis(); return 0; }
We can see that the two printouts are the same:
We can see that we didn't write assignment operator overload ourselves, but we did succeed in assignment and assigned correctly. We will explain here. The system provides default assignment operator overload. It is also a kind of shallow assignment behavior. We need to understand the difference between copy constructor and assignment operator overload. Copy constructor does not exist in the past and directly copies one copy. Assignment operator overload has two copies. Then take the first copy and overwrite the second copy.
If there is no heap memory space in the object, it can meet the requirements by default.
Fixed format syntax
Once self implemented, the default will not exist
If we implement it but there is no content in it, we cannot copy it:
#include <iostream> using namespace std; struct Data { public: Data(int y = 2016, int m = 6, int d = 6) :year(y), month(m), day(d), space(new char[1024]) {} Data& operator = (const Data& another) { } void dis() { cout << " year " << year << " month " << month << " day " << day << endl; } private: int year; int month; int day; char* space; }; int main() { Data d(2018, 8, 8); d.dis(); Data d2(2019, 9, 9); d2 = d; d2.dis(); return 0; }
The operation result is:
We can see that there is no overload success.
Then we implement operator overloading by ourselves:
#include <iostream> using namespace std; struct Data { public: Data(int y = 2016, int m = 6, int d = 6) :year(y), month(m), day(d), space(new char[1024]) {} Data& operator = (const Data& another) { this->year = another.year; this->month = another.month; this->day = another.day; return *this; } void dis() { cout << " year " << year << " month " << month << " day " << day << endl; } private: int year; int month; int day; char* space; }; int main() { Data d(2018, 8, 8); d.dis(); Data d2(2019, 9, 9); d2 = d; d2.dis(); return 0; }
The operation result is:
We can see that the operator overloading implemented in the above example is the same as that provided by the system.
Let's explain why return * this is added to operator duplication:
We only give the code in the main function, other codes remain the same:
int main() { Data d(2018, 8, 8); d.dis(); Data d2(2019, 9, 9); d2 = d; d2.dis(); //Use to return this pointer Data d3; d3 = d2 = d; //It is not the same as the following line of code d3.operator=(d2.operator=(d)); return 0; }
The above meaning is: d is assigned to d2, the whole expression returns d2, and d2 is passed as a parameter, and d2 is assigned to d3.
Problems in self realization
Reanalysis
Then, when memory is released, there will be a problem of repartition.
Memory leak
Solution: first release the previous memory, and then make a deep copy.
Self assignment
Self assignment means that when self assignment occurs, the original memory space is released, but the original memory space is still its own. If it is released, the assignment operator cannot be overloaded, so we need to solve this problem in self implementation.
Solve
Code implementation:
#include <string.h> #include <iostream> using namespace std; struct Data { public: Data(int y = 2016, int m = 6, int d = 6) :year(y), month(m), day(d), space(new char[1024]) {} Data& operator = (const Data& another) { if (this == &another) //Solve the problem of self assignment return *this; //Realize chain expression else { delete[]this->space; //Resolve memory leaks space = new char [strlen(another.space) + 1]; strcpy(space, another.space); } } ~Data() //Solve the problem of reanalysis { cout << "~~~~~~~~" << this << endl; //Pointer to the current object delete[]space; } void dis() { cout << " year " << year << " month " << month << " day " << day << endl; } private: int year; int month; int day; char* space; }; int main() { Data d(2018, 8, 8); d.dis(); Data d2(2019, 9, 9); d2 = d; d2.dis(); return 0; }
The above self implementation code solves these three problems.
Next we show that we are
Data & operator = (const Data& another)
During the delivery, the content is const, which means that the content in another will not be modified
Data& operator = (const Data& another)
There is no reference at the front, so you can return the content of this pointer. If you add the
const Data& operator = (const Data& another)
We can see that if const is used outside the reference, it can be assigned. If you don't want to be assigned, you can add const in the front.
For example: (d3 = d2) = d; if there is const before it, the expression cannot be assigned.