effective C++ 条款 11:在operator= 处理‘自我赋值’
2012-01-13 21:34
483 查看
假设建立一个class来保存一个指针指向一块儿动态分配的位图(bitmap)
Widget& Widget::operator=(const Widget& rhs)
{
Bitmap* pOrig = pb;
pb = new Bitmap(*rhs.pb);
delete pOrig;
return *this;
}
这样如果new Bitmap抛出异常,pb 保持原状。即使没有证同测试,还是能够处理自我赋值,只是不是最高效的办法,但他行得通。如果关心效率, 把“证同测试”加上,但是这项测试本身也需要成本,是代码变大,并导入一个新的控制流分支,而且“自我赋值”的发生频率并不高。
确保代码不但“异常安全”而且“自我赋值安全”的一个替代方案是,使用所谓的copy and swap技术:
class Bitmap{...};
class Widget
{
public:
protected:
private:
Bitmap* pb;
};
这个operator=实现代码表面看上来合理, 但自我赋值出现时并不安全,也不具备异常安全性。
class Widget
{
public:
protected:
private:
Bitmap* pb;
};
这个operator=实现代码表面看上来合理, 但自我赋值出现时并不安全,也不具备异常安全性。
Widget& Widget::operator=(const Widget& rhs)
{
delete pb;
pb = new Bitmap(*rhs.pb);
return *this;
}
rhs和*this可能是同一个对象。这样的话delete就不只是销毁当前对象的bitmap,它也销毁rhs的bitmap。
预阻止这种错误,传统的做法是在operator=的最前面的一个“证同测试”identity test。{
delete pb;
pb = new Bitmap(*rhs.pb);
return *this;
}
rhs和*this可能是同一个对象。这样的话delete就不只是销毁当前对象的bitmap,它也销毁rhs的bitmap。
Widget& Widget::operator=(const Widget& rhs)
{//证同测试,如果是自我赋值就不做任何事
if (this == &rhs)
{
return *this;
}
delete pb;
pb = new Bitmap(*rhs.pb);
return *this;
}
还不具备“异常安全性”,如果“new Bitmap”导致异常(不论是因为分配时内存不足,还是因为Bitmap的copy构造函数抛出异常),Widget最终会有一个指针指向一快被删除的Bitmap。
让operator=具备“异常安全性”往往自动获得“自我赋值安全”的回报。如下代码,只需注意在复制pb所指东西之前别删除pb:{//证同测试,如果是自我赋值就不做任何事
if (this == &rhs)
{
return *this;
}
delete pb;
pb = new Bitmap(*rhs.pb);
return *this;
}
还不具备“异常安全性”,如果“new Bitmap”导致异常(不论是因为分配时内存不足,还是因为Bitmap的copy构造函数抛出异常),Widget最终会有一个指针指向一快被删除的Bitmap。
Widget& Widget::operator=(const Widget& rhs)
{
Bitmap* pOrig = pb;
pb = new Bitmap(*rhs.pb);
delete pOrig;
return *this;
}
这样如果new Bitmap抛出异常,pb 保持原状。即使没有证同测试,还是能够处理自我赋值,只是不是最高效的办法,但他行得通。如果关心效率, 把“证同测试”加上,但是这项测试本身也需要成本,是代码变大,并导入一个新的控制流分支,而且“自我赋值”的发生频率并不高。
class Widget
{
public:
void swap(Widget& rhs); //交换*this和rhs的数据
protected:
private:
Bitmap* pb;
};
Widget& Widget::operator=(const Widget& rhs)
{
Widget temp(rhs);
swap(temp);
return *this;
}
这个主题的另一个变奏曲:1.copy assignment操作符可能被声明为“以by value方式接受实参”;2.以by value方式传递东西会造成一份副本:
Widget& Widget::operator=(Widget rhs) //pass by value
{
swap(rhs);
return *this;
}
确保当对象自我赋值时operator=有良好行为。其中技术包括比较“来源对象”和“目标对象”的地址、精心周到的语句顺序、以及{
public:
void swap(Widget& rhs); //交换*this和rhs的数据
protected:
private:
Bitmap* pb;
};
Widget& Widget::operator=(const Widget& rhs)
{
Widget temp(rhs);
swap(temp);
return *this;
}
这个主题的另一个变奏曲:1.copy assignment操作符可能被声明为“以by value方式接受实参”;2.以by value方式传递东西会造成一份副本:
Widget& Widget::operator=(Widget rhs) //pass by value
{
swap(rhs);
return *this;
}
copy and swap。
确定任何函数如果操作一个以上的对象,而其中有多个对象是同一个时,其行为仍然正确。
相关文章推荐
- Effective C++ 条款11:在operator=中处理"自我赋值"
- Effective C++_笔记_条款11_在operator=中处理“自我赋值”
- 《Effective C++》学习笔记条款11 在operator =中处理“自我赋值”
- 读书笔记《Effective c++》 条款11 在operator= 中处理“自我赋值”
- Effective C++:条款11:在operator= 中处理“自我赋值”。
- Effective C++ -----条款11: 在operator=中处理“自我赋值”
- Effective C++ 条款10 令operator=返回一个reference to *this 条款11 在operator=中处理"自我赋值"
- 【Effective c++】条款11:在operator=中处理“自我赋值”
- 条款11 在operator=中处理“自我赋值”
- 条款11:在operator=中处理“自我赋值”(Handle assignment to self in operator=.)
- 条款11 在operator=中处理“自我赋值“
- 条款11:在operator = 中处理"自我赋值"
- Effective C++——》条款11:在operator=中处理自我赋值
- 条款11:在operator=中处理“自我赋值”
- 条款11: 在operator= 中处理"自我赋值"
- 条款11:在operator=处理自我赋值
- 条款11:在operator=中处理”自我赋值“
- 《Effect C++》学习------条款11:在 operator= 中处理“自我赋值”
- EC读书笔记系列之6:条款11 在operator=中处理自我赋值
- Effective C++ 学记之11 在operator=中处理“自我赋值“