Effective C++——operator =

来源:互联网 发布:中美网络安全问题 编辑:程序博客网 时间:2024/06/06 09:16

**

让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_);获得新的内存空间;此时即使是自我赋值也不会影响,因为没有delete3.最后清理内存空间 delete temp ;注:此时如果是自我赋值,即使没有identity test也不会出错。因为第二步指针指向的内存空间内容还是正常数据,唯一区别是指针本身数值不一样了而已。当然,这里也可以再加上identity test验证,由于自我赋值的概率并不高,验证代码被执行可能性不大,但验证代码本身会带来测试成本,同时执行效率降低。

还有另外一种方法来满足异常安全与自我赋值条件,即copy-and-swap技术,与异常安全密切相关,不在这里继续讨论了。

0 0
原创粉丝点击