C++ 自赋值

https://harttle.land/2015/07/30/effective-cpp-11.html,这个讲的很不错!

1.存在的问题

因为cpp中有指针和引用,它们可以指向同一个变量,所以会存在自赋值的问题。

a[i] = a[j];     //@ 如果i和j有同样的值,这里就是一次自赋值
*px = *py;        //@ 如果px和py指向相同的东西,这里就是一次自赋值 

自赋值一般存在:自赋值安全和异常安全,两个问题,例如:

自赋值安全

Widget& Widget::operator=(const Widget& rhs){
    delete pb;                   // stop using current bitmap
    pb = new Bitmap(*rhs.pb);    // start using a copy of rhs's bitmap
    return *this;                // see Item 10
}

当是自赋值的时候,pb已经先被删除了,那么后面的new就会为空,这是未知的计算。

异常安全

Widget& Widget::operator=(const Widget& rhs){
    if (this == &rhs) return *this;
    delete pb;                   // stop using current bitmap
    pb = new Bitmap(*rhs.pb);    // start using a copy of rhs's bitmap
    return *this;                // see Item 10
}

这个自赋值安全,但是没有异常安全,如果new处出现了异常,那么pb仍旧指向空。

2.解决办法

通过调整语句顺序

Widget& Widget::operator=(const Widget& rhs){
    Bitmap *pOrig = pb;               // remember original pb
    pb = new Bitmap(*rhs.pb);         // make pb point to a copy of *pb
    delete pOrig;                     // delete the original pb
    return *this;
}

通过一个中间变量来实现,而没有使用if的判断,因为可能会影响效率。

其实也可以这样:

    HasPtr & operator=(const HasPtr& hp){
        std::string * t=new std::string(*hp.ps);
        delete ps;
        ps=t;
        i=hp.i;
        return *this;
    }

主要就是申请一个临时变量来指向原来的空间或者是新申请的空间。//delete应该是不会出现异常的吧。

通过swap,赋值和交换

Widget& Widget::operator=(Widget rhs){
    swap(rhs);                // swap *this's data with
    return *this;             // the copy's
}

注意参数为值拷贝,在cpp459页有讲解,

C++ 自赋值

 

 总结:

  1. 判断两个地址是否相同
  2. 仔细地排列语句顺序
  3. Copy and Swap

自赋值存在的知识点差不多这些。

上一篇:Memcached的安装和应用


下一篇:Memcached总结二:Memcached环境安装设置以及连接memcache服务器