You can easily assign an object to itself without knowing it.
1 | // Example 1 |
It is dangerous to assign an object to itself if your class doesn’t handle this kind of operator appropriately. Let’s consider an example here:
1 | class Bitmap{...}; |
You will be dead if you assign a Widget object to itself cause you will end up with holding a pointer to a deleted object!
One way, but not best way to deal with self assignment is to write code to explicitly deal with this situation:
1 | Widget& Widget::operator=(const Widget& rhs) |
This is not the best way to solve the problem cause this operator is not exception-safe. What does this mean? Imagine what if an exception is thrown when
1 | pb = new Bitmap(*rhs.m_pb); |
is been executed (for example, not enough memory), then the object will hold a pointer to a deleted Bitmap.
Luckily, making operator= exception-save typically renders it self-assignment-safe, too. So the best way to accomplish that is:
1 | Widget& Widget::operator=(const Widget& rhs) |
Now if “new Bitmap” throws an exception, pb remains unchanged. Even without the identity test, this code handles assignment to self, because we make a copy of the original bitmap, point to the copy we made, and then delete the original bitmap.