我们来看看下面一段代码,class Widget中自己实现了拷贝构造函数
class Bitmap
{
};
class Widget
{
public:
Widget ()
{
pb = new Bitmap;
}
Widget& operator=(const Widget &rhs);
private:
Bitmap *pb;
};
下面有三种方式对Widget& operator=(const Widget &rhs)的实现;
方式1:
Widget& Widget::operator=(const Widget &rhs)
{
delete pb;
pb = new Bitmap( *(rhs.pb));
return *this;
}
下面我测试该类:
void main()
{
Widget w;
Widget *pa, *pb;
pw1 = &w;
pw2 = &w;
*pw1 = *pw2;
}
由于pb和pa指向了同一个对象,而我们在执行*pw1 = *pw2时,我们自己写的copy assignment操作中的delete不仅销毁了当前对象的Bitmap,也销毁了rhs中的Bitmap;
方式2:
Widget& Widget::operator=(const Widget &rhs)
{
if ( this == &rhs)
{
return *this;
}
delete pb;
pb = new Bitmap( *(rhs.pb));
return *this;
}
很好,这里可以解决自我赋值的问题,但是如果new Bitmap( *(rhs.pb))失败,Widget最终会持有一个指针指向一块被删除的Bitmap,这样的指针是有害的。你无法安全地删除它们,甚至无法安全地读取它们。实际这里存在“异常安全性”问题。
方式3:
Widget& Widget::operator=(const Widget &rhs)
{
Bitmap *pOrig = pb;
pb = new Bitmap(*rhs.pb);
if ( NULL == pb )
{
pb = pOrig;
}
else
{
delete pOrig;
}
return *this;
}
这里可以解决自我赋值的问题,也可以解决“异常安全性”的问题,当new Bitmap( *(rhs.pb))失败时,pb就保持原状。