C++中赋值函数operator=潜在的“自我赋值安全性”和“异常安全性”

看下面一段代码:

class Bitmap { ... }
class Widget
{
    public:
        Widget& operaotr=(const Widget& wg);
    private:
        Bitmap* bp;
}

Widget& operator=(const Widget& wg)
{
    delete bp;
    bp = new Bitmap(*wg.bp);
    return *this;
}

上面的一段简单的赋值函数,看上去逻辑很正确:首先释放掉bp所指的当前对象,然后将其指向新的对象,并返回指向this的引用。如果仔细分析,会发现存在下面两个问题:

1)如果bp与wg的bp所指的是同一对象,那么delete bp后,wg的bp也将指向一个已经删除的对象,最终bp所指的也是一个已经删除的对象,从而出现错误。

2)如果上面的问题没有出现,但new一个Bitmap的时候出现了异常(内存分配不足或者拷贝构造函数出现异常等),那么最终得到的pb还是指向一个已经删除的对象。

为了解决上面的问题,可以先将bp指向新的对象,然后再释放掉其原来指向的对象。

例如:

Widget& operator=(const Widget& wg)
{
    Bitmap* srbp = bp;
    bp = new Bitmap(*wg.bp);
    delete srbp;
    return *this;
}

或者如下方法,将wg的数据制作一个副本,然后将这个副本数据与*this数据交换。

Widget& operator=(const Widget& wg)
{
    Widget ob(wg);
    swap(ob);
    return *this;
}


整理子Effective C++第3版case 11。

 

 

posted on 2013-05-10 17:39  Sophia-呵呵小猪  阅读(258)  评论(0编辑  收藏  举报