Article 11: Handling "self-assignment" in operator=
It is necessary to consider self-assignment when implementing operator=, like X=y. We don't know if the value of the variable x and Y represents the same value (it is more appropriate to say X and y as a pointer).
For example, the following
First edition:
#include <iostream>using namespace Std;class bitmap{public:bitmap () {cout<< "Call Bitmap () No participation constructor" << Endl;} Bitmap (const bitmap& BT) {this->i = bt.i;cout<< "Call bitmap () copy constructor" <<endl;} ~bitmap () {}private:int i;}; Class Widget{public:widget () {PB = new bitmap ();} Widget (const widget& wd) {THIS->PB = WD.PB;} public:widget& operator= (const widget& RHS);p rivate:bitmap* PB; Defines an object allocated from the heap};//First Edition assignment function:widget& widget::operator= (const widget& RHS) {Delete PB;PB = new Bitmap (*RHS.PB) ; return *this;} This version of the function of PB before use to clean up before the PB point. It is very logical to accept another new object, but//when this is equal to the function parameter RHS, PB = new Bitmap (*RHS.PB); Because we've dropped the *RHS.PB delete.int main () {Widget W1; Widget w2;w1 = W2;return 0;} /* Call Bitmap () non-participating constructor call bitmap () no constructor call bitmap () copy constructor Press any key to continue*/
Second Edition:
Second Edition assignment function:widget& widget::operator= (const widget& RHS) {if (this = = &RHS) {return *this;} Delete PB;PB = new Bitmap (*RHS.PB); return *this;} This version of the line, the assignment function is basically acceptable, but not necessarily safe, because when new generates an exception, PB is still a//indeterminate pointer.
Third edition:
The third edition of the assignment function:widget& widget::operator= (const widget& RHS) {Bitmap *porig = PB;PB = new Bitmap (*RHS.PB);d elete Porig; return *this;} The third version of the function starts with a porig record of PB. When new does not have an exception, we then release the PB's original pointing space//to improve security. Such a method can also handle self-assignment. If it rhs=*this here. We first made a backup of the original//bitmap, delete the original bitmap, point to our copy of the backup, perhaps this method of handling self-assignment//is not very good. However, it is very good to use this method in the case of security.
Fourth edition:
#include <iostream>using namespace Std;class bitmap{public:bitmap () {cout<< "Call Bitmap () No participation constructor" << Endl;} Bitmap (const bitmap& BT) {this->i = bt.i;cout<< "Call bitmap () copy constructor" <<endl;} ~bitmap () {}private:int i;}; Class Widget{public:widget () {cout<< "Call Widget () No participation constructor" <<ENDL;PB = new Bitmap ();} Widget (const widget& wd) {cout<< "Call Widget () copy constructor" <<ENDL;THIS->PB = WD.PB;} void My_swap (widget& rhs);p ublic:widget& operator= (const widget& RHS);p rivate:bitmap* PB; Defines an object allocated from the heap};//the fourth edition assignment function: void Widget::my_swap (widget& rhs) {PB = RHS.PB;} widget& widget::operator= (const widget& RHS) {Widget temp (RHS);//Prevent Change Rhsmy_swap (temp); return*this;} The fourth edition of the assignment function takes advantage of the copy and Swap technique, which is specified in clause 29//. Not really looking, this is not explained here. The fourth version is also able to use:widget& widget::operator= (Widget rhs) {my_swap (RHS);///In fact it is essentially the same, because the passed parameter is a value pass, so here is a copy of the RHS. Equivalent to widget temp (RHS), mainly to prevent RHS from being changed. Return*this;} int main () {Widget W1; Widget w2;w1 = W2;return 0;} /* Call Widget () No participation constructor calls BITMap () non-participating constructor call widget () no constructor call bitmap () non-participating constructor call widget () copy constructor Press any key to continue*/
Summarize:
1: Make sure that when an object is self-assigned, operator= has good behavior, and the technology includes the address of "original object" and "target object". , thoughtful sequence of statements, and copy and swap
2: Determines whether or not the function assumes the operation of more than one object, and when more than one object is the same object, its behavior is still correct.
Effective C + + reading notes clause 11