自行管理资源时,可能在停止使用资源之前意外释放了它。
class Data{...};
class Widget{
...
private:
Data* pd;
};
Widget& Widget::operator=(const Widget& rw)
{
delete pd;
pd = new Data(*rw.pd);
return *this;
}
operator=函数内的*this和rw可能是同一对象,结果就是Widget对象持有一个指针指向一块已被删除的Data。
- 自我赋值安全性
- 异常安全性
添加证同测试:
Widget& Widget::operator=(const Widget& rw)
{
if(this == &rw) return *this;
delete pd;
pd = new Data(*rw.pd);
return *this;
}
如果"new Data"导致异常(内存不足或copy构造抛出异常),结果和上面一样。
- 自我赋值安全性
- 异常安全性
一般情况下,让operator=具备“异常安全性”往往自动获得“自我赋值安全性”
Widget& Widget::operator=(const Widget& rw)
{
Data* tmp = pd;
pd = new Data(*rw.pd);
delete tmp;
return *this;
}
delete 延后,如果"new Data"导致异常,pb将保持原状。
在operator=函数内手工排列语句的一个好的替代方案是使用,copy and swap技术,条款29。
- 确保当对象自我赋值时operator=有良好行为。其中技术包括比较“来源对象”和“目标对象”的地址、精心周到的语句顺序、以及copy-and-swap。
- 确定任何函数如果操作一个以上的对象,而其中多个对象是同一个对象时,其行为仍然正确。