正常来说自我赋值是一个很愚蠢的行为,但是有一些自我赋值其实是不太容易察觉的。
例:
a[i] = a[j] //i = j 就是自我赋值
*px = *py //px py指向同一块内容就是自我赋值
甚至类型不同也可能是,自我赋值
class base{};
class derived : public base{};
void fun(base &b, derived *d);
因为父类对象的指针可以指向派生类对象。
这种自我赋值会引起引起申请的资源在没有被使用完,就被释放的错误
class bitmap
{
class Widget
{
private:
bitmap *ptr //指向一块堆空间
}
};//不安全的operator
Widget&Widget::operator=(const Widget &rhs)
{
delete ptr;
ptr = new Widget(rhs);
return *this;
}如果rhs和ptr指向同一个对象,rhs已经被销毁了。
第一种解决办法
只需要判断一下,rhs和*this是否相等。
Widget&Widget::operator=(const Widget &rhs)
{
if(rhs == *this)//
return *this;
delete ptr;
ptr = new bitmap(*rhs.pb);
return *this;
}
第二种解决办法copy and swap
Widget&Widget::operator=( Widget rhs)//利用函数传值,是对原值的拷贝
{
swap(rhs);//将rhs和*this的数据交换
return *this;
}
相比第一种写法,这种写法的效率更高,判断是需要成本的,会使代码变大,引入一个新的控制流分支,二者都会降低运行速度
copt-and-swap是一个高效简介的技术,非常好用。