自我赋值出现在对象自己给自己赋值的过程中。
有时候容易察觉,有时候不容易察觉。特别是当在有继承关系的类对象中,一个基类的引用或指针可以指向子类的对象。
class Book{};
class Store{
private:
Book *pb;//指向一个从heap分配的对象
}
Store & Store::operator = (const Store & st)
{
delete pb;
pb = new Stroe(*st.pb);
return *this;
}
上面的这个程序有问题,不仅没有(self-assignment-safe)自我赋值安全性而且也没有(exception safety)异常安全性。
因为st跟*this可能是同一个对象,所以当delete pb的时候也delete掉了st中的Book对象。最后return的时候,发现这个st中的指针指向了一个被删除的对象。
防止这种的方法有进行检验是否是同一个对象。
Store & Store::operator = (const Store & st)
{
if(this==&st)
return *this;//如果是同一个对象,那么直接返回这个对象就可以
delete pb;
pb = new Stroe(*st.pb);
return *this;
}
然后一个问题是异常安全性
在new操作的时候可能会抛出异常,但此时pb已经被删除掉,造成了这个对象的执政指向了一个被删除的对象。
改进的方法如下:
Store & Store::operator = (const Store & st)
{
Book * bt = pb;
pb = new Stroe(*st.pb);
delete bt;
return *this;
}
这样如果new抛出异常,那么pb还将保持原有的指针。
更高级一点的技术是:
用手工的方法安排赋值语句的顺序
Stroe{
void swap(Store &st);//这个函数的作用是交换*this 与st中的数据
}
Store & Store::operator = (const Store & st)
{
Stroe stemp(st);
swap(stemp);
return *this;
}
//如果采用的是传值可以用下面的代码来实现
Store & Store::operator = ( Store st)
{
swap(stemp);//传值时形参会有一个临时对象,所有不必像上面一样创建临时对象了
return *this;
}
通过上面的操作,实现了 operator=操作符的安全性。
来你博客踩踩,欢迎互访,可以申请友情链接吗?可以的话给我回个邮件吗?我的网址是http://www.sheyingrumen.net,谢谢
可以啊
过来学习了。。。
呵呵,互相学习