Item 11: Handle assignment to self in operator=
Concept
Self-assignment occurs when an object is assigned to itself (w = w). This can happen less obviously through aliasing (two pointers or references referring to the same object). A naive implementation of operator= might delete a resource before copying it, which is catastrophic during self-assignment. The traditional fix is an identity test, but a better approach is the copy-and-swap idiom, which is both self-assignment-safe and exception-safe.
Code Example
class Bitmap { /* ... */ };
class Widget {
Bitmap* pb;
public:
// Approach 1: Identity test (not exception-safe without more work)
Widget& operator=(const Widget& rhs) {
if (this == &rhs) return *this; // identity test
delete pb;
pb = new Bitmap(*rhs.pb);
return *this;
}
// Approach 2: Copy-and-swap (preferred — both self-assignment and exception safe)
Widget& operator=(const Widget& rhs) {
Widget temp(rhs); // make a copy
swap(temp); // swap *this with the copy
return *this;
}
void swap(Widget& other) {
std::swap(pb, other.pb);
}
};
Things to Remember
- Make sure
operator=is well-behaved when an object is assigned to itself. Techniques include comparing addresses of source and target objects, careful statement ordering, and copy-and-swap. - Make sure that any function operating on more than one object behaves correctly if two or more of the objects are the same.