例子:一个不安全的自我赋值
Widget& Widget::operator=(const Widget& rhs)
{
delete pb;
pb=new Bitmap(*rhs.pb);
return *this;
}
上面的这段代码当自我赋值时,会发生错误,因为开始就将pb给delete了,所以*rhs.pb也没有了。
添加了一个证同测试以达到自我赋值检测目的:
Widget& Widget::operator=(const Widget& rhs)
{
if(this==&ths)
return *this;
delete pb;
pb=new Bitmap(*rhs.pb);
return *this;
}
如果相同就直接返回*this而不用赋值。
但是上述代码却不具备“异常安全性”,当new Bitmap(*rhs.pb)出现异常时(可能内存不足等原因导致),那么我们将指向一个空的地址内存块。
于是我们再次改变代码:
Widget& Widget::operator=(const Widget& rhs)
{
Bitmap* pOrig=pb;
pb=new Bitmap(*rhs.pb);
delete pOrig;
return *this;
}
以上我们首获取pb的一个副本,当发生自我赋值时,我们先获取自我的一个副本,然后pb指向一个新的内存(由*rhs.pb赋值),然后再利用副本来清空旧的内存。当发生异常时,下面的代码都不会执行了,而我们的pb却仍保持原状,所以具有异常安全。
最后一种即保证“自我赋值安全”和“异常安全的”的操作为copy and swap技术。
Widget& Widget::operator=(const Widget& rhs)
{
swap(rhs);
return *this;
}
这样就算自我赋值和出现异常也没关系。