条款11:记得在operator=中处理自赋值的情况。
本来的版本是这样的:
1 Widget & Widget::operator=(Widget rhs) 2 { 3 delete pb;//这里可能直接将rhs的pb删除了 4 pb = new (*rhs.pb); 5 return *this; 6 }
这里的代码完全无法处理自赋值的情况,一般是在operator的真正处理之前加上一个“证同测试”,像下面这样:
1 Widget& Widget::operatpr=(const Widget & rhs) 2 { 3 if(*this == rhs) 4 return *this; 5 else 6 { 7 delete pb;//pb是对象中的一个指针 8 pb = new(*rhs.pb); 9 return *this; 10 } 11 }
其实下面这种做法更好,因为上面的情况如果在new的时候抛出异常带来的伤害会比较大。
Widget& Widget::operator=(const Widget & rhs) { Bitmap *pOrig = pb; pb = new Bitmap(*rhs.pb);//这样做的好处就是不用担心在new的时候会产生什么伤害。 delete pOrig; return *this;//这里经过了精心的调整顺序 }
还有一种方式采用所谓的copy and swap技术;
Widget & Widget::operator=(Widget rhs) { Widget temp(rhs); swap(temp); return *this; }
小结:确保当对象自我赋值的时候有较好的行为,基本的技术包括:比较来源对象与目的对象的地址, 精心的调整语句顺序, 以及copy-and-swap技术。