Effective C++——operator =
2015-09-18 16:48
627 查看
**
说明:Widget& operator=(const Widget& obj)函数返回值需要是类的一个引用,目的是为了支持链式编程,否则不支持连等赋值操作。
**
考虑以下自我赋值的情况
1.Widget w;
w= w;
2. a[i] = a[j];
3. *px = *py;
4. 基类和子类之间的赋值
说明:在w1 = w1 ;语句之后会发生什么?
解决方案:传统做法是进行一个identity test
如何解决这两个问题?
庆幸的是在解决了异常安全性的同时可以避免自我赋值安全性
还有另外一种方法来满足异常安全与自我赋值条件,即copy-and-swap技术,与异常安全密切相关,不在这里继续讨论了。
让operator = 返回一个reference to *this
**#include <iostream> using namespace std; class Widget { public: Widget(){} ~Widget(){} Widget& operator=(const Widget& obj) { //TODO:赋值操作 return *this; } }; int main() { Widget w1,w2,w3; w1 = w2 = w3; cin.get(); return 0; }
说明:Widget& operator=(const Widget& obj)函数返回值需要是类的一个引用,目的是为了支持链式编程,否则不支持连等赋值操作。
**
在operator = 中处理自我赋值
**考虑以下自我赋值的情况
1.Widget w;
w= w;
2. a[i] = a[j];
3. *px = *py;
4. 基类和子类之间的赋值
#include <iostream> using namespace std; class Bitmap { }; class Widget { public: Widget(){} ~Widget(){} //1.缺少异常安全性 //2.缺少自我赋值安全性 Widget& operator=(const Widget& obj) { delete pBitmap_; this->pBitmap_ = new Bitmap(*obj.pBitmap_); return *this; } private: Bitmap *pBitmap_; }; int main() { Widget w1; w1 = w1; cin.get(); return 0; }
说明:在w1 = w1 ;语句之后会发生什么?
Widget& operator=(const Widget& obj)函数内部的*this 与obj在自我赋值时是同一个对象,这样的话,delete pBitmap_执行之后会清理obj对象,this->pBitmap_ = new Bitmap(*obj.pBitmap_);这句之后获得的内容将是垃圾内容,因为被清理了。
解决方案:传统做法是进行一个identity test
//仍缺少异常安全性 Widget& operator=(const Widget& obj) { if(this == &obj) { return *this; } delete pBitmap_; this->pBitmap_ = new Bitmap(*obj.pBitmap_); return *this; }
说明:this->pBitmap_ = new Bitmap(*obj.pBitmap_); 内存分配失败或Bitmap拷贝构造函数抛出异常,都将导致pBitmap_ 指向一片垃圾空间
如何解决这两个问题?
庆幸的是在解决了异常安全性的同时可以避免自我赋值安全性
Widget& operator=(const Widget& obj) { Bitmap* temp = pBitmap_; this->pBitmap_ = new Bitmap(*obj.pBitmap_); delete temp ; return *this; }
思路:异常安全性主要是因为先delete 后又拷贝指针指向的内存空间内容了,当自我赋值时就发生了错误。 现在改为后delete,但这样就容易把刚分配的内存空间给清理了,如此自然想到需要一个临时变量存储之前的指针信息。 1.Bitmap* temp = pBitmap_; 保存旧的需要清理的内存空间指针信息; 2.this->pBitmap_ = new Bitmap(*obj.pBitmap_);获得新的内存空间;此时即使是自我赋值也不会影响,因为没有delete 3.最后清理内存空间 delete temp ; 注:此时如果是自我赋值,即使没有identity test也不会出错。因为第二步指针指向的内存空间内容还是正常数据,唯一区别是指针本身数值不一样了而已。 当然,这里也可以再加上identity test验证,由于自我赋值的概率并不高,验证代码被执行可能性不大,但验证代码本身会带来测试成本,同时执行效率降低。
还有另外一种方法来满足异常安全与自我赋值条件,即copy-and-swap技术,与异常安全密切相关,不在这里继续讨论了。
相关文章推荐
- C语言改变循环的状态
- C语言中动态分配数组
- C++中传递数组参数的几种用法和注意点
- swig C#链接c++ dll
- Effective C++——条款45(第7章)
- c++ 抽象概念,内存格局,浅拷贝,深拷贝,临时对象,无名对象
- C++中不能被定义为虚函数的函数
- 详解C++编程中的单目运算符重载与双目运算符重载
- c/c++复习日记 1.不带缓存的I/O和标准I/O
- C++运算符重载规则详解
- 矩阵乘法算法
- 简介C++编程中的运算符重载
- C++ Primer Plus 第6版 中文版 第7章编程练习
- C++读入输出优化
- 【C++】vector、list、map、set
- C++:类和对象
- c语言 词法分析
- c/c++ 中结构体的初始化与类的初始化的不同之处
- C++ typeid() 基类必须是多态类
- Java和C++程序在编译和运行上有什么区别