条款11 在operator=中处理自我赋值
继续参考上例,当用户调用方法如下时,会有什么问题?
int main()
{
Cat A("huahua",5);
A = A;
}
正常通过。
考虑如下情况
class CatOwner
{
public:
CatOwner(std::string name = "lily",std::string cat_name ="huahua"):name_(name)
{
pcat_ = new Cat(cat_name);
}
~CatOwner()
{
delete pcat_;
}
CatOwner &operator=(const CatOwner &rhs)
{
this->name_ = rhs.name_;
delete this->pcat_;
this->pcat_ = nullptr;
this->pcat_ =new Cat(*rhs.pcat_);
return *this;
}
void Print()
{
if(pcat_ )
pcat_->Print();
else
std::cout << " no cat " << std::endl;
std::cout << " Owner is " << name_ << std::endl;
}
private:
Cat *pcat_;
std::string name_;
};
int main()
{
CatOwner A("LiLei","leilei");
CatOwner B("HanMeimei","meimei");
A = B;
CatOwner C("LiMing","mingming");
C =C ;
}
编译通过,执行时,报段错误。原因,调用 C=C
时,先释放了pcat_指针,并修改为nullptr, 访问了空指针。
如下修改
CatOwner &operator=(const CatOwner &rhs)
{
if(*this == rhs)
return *this;
this->name_ = rhs.name_;
delete this->pcat_;
this->pcat_ = nullptr;
this->pcat_ =new Cat(*rhs.pcat_);
return *this;
}
编译运行正常。
但,如果在 this->pcat_ =new Cat(*rhs.pcat_);
时抛出异常了,也会导致数据丢失。
再做如下修改
CatOwner &operator=(const CatOwner &rhs)
{
if(*this == rhs)
return *this;
this->name_ = rhs.name_;
Cat *pcat_temp = this-> pcat_;
this->pcat_ =new Cat(*rhs.pcat_);
delete pcat_temp;
pcat_temp = nullptr;
return *this;
}
copy and swap
void CatOwner::swap(const CatOwner &rhs)
{
//todo 见条款29
}
CatOwner &operator=(const CatOwner &rhs)
{
CatOwner Temp(rhs);
swap(Temp);
return *this;
}