zoukankan      html  css  js  c++  java
  • 第九章:重载赋值运算符中需要注意的两个问题

    前言

           如果系统自动生成的赋值运算符重载函数不合乎你的要求,那么就应当定制自己的赋值运算符。

           然而,定制赋值运算符有两点是非常值得注意的,本文将讲解这两点,让你写出更优质的 =运算符。

    第一点:请返回 reference to *this

           我们经常使用如 "a=b=c=1" 这种形式的连锁赋值语句,而重载的赋值运算符自然也应当能够这样使用。

           因此,在重载运算符函数末尾请写上如这样的语句 return *this;

           除了赋值运算符,+=,-=这样的赋值运算符同样需要这样做。

    第二点:处理好自我赋值

           首先,我们看一段问题代码:

     1 // 位图资源类
     2 class Bitmap { /*......*/ };
     3 
     4 // 位图资源管理类
     5 class Widget {
     6 public:
     7     //......
     8     Widget & operator=(const Widget & rhs);
     9     //......
    10 private:
    11     //......
    12     Bitmap *pb;    // 位图资源。指针类型,指向 heap 分配而得的空间
    13     //......
    14 };
    15 
    16 Widget & Widget::operator=(const Widget & rhs)
    17 {
    18     delete pb;    // 删除原有资源
    19     pb = new Bitmap(*rhs.pb);    // 申请新的资源并存放右操作数的数据
    20     return *this;
    21 }

           问题出在重载函数中,如果左右操作数是相同的对象,delete 掉原有资源之后,所有数据信息就全丢了。

           因此,运算符重载函数需要加上一个证同测试:

     1 Widget & Widget::operator=(const Widget & rhs)
     2 {
     3     // 加入证同测试
     4     if (this == &rhs)
     5         return *this;
     6 
     7     delete pb;    // 删除原有资源
     8     pb = new Bitmap(*rhs.pb);    // 申请新的资源
     9 
    10     return *this;
    11 }

           但这依然不是最好的做法:因为 new 有可能失败,导致资源丢失。

           下面这个精心设计的重载函数才是我们需要的:

    1 Widget & Widget::operator=(const Widget & rhs)
    2 {
    3     Bitmap * pOrig = pb;
    4     pb = new Bitmap(*rhs.pb);
    5     delete pOrig;
    6 
    7     return *this;
    8 }

           这个实现就保证了赋值的安全,健壮,是个非常可取的方案。

    小结

           赋值运算符还有一些其他的非常可取的实现,这里就不一一讲解了。

  • 相关阅读:
    Assembly介绍
    How to be a Programmer
    (转) 展望未来,总结过去10年的程序员生涯,给程序员小弟弟小妹妹们的一些总结性忠告
    ClientScript.RegisterStartupScript()
    sql server日期时间转字符串
    GridView 全选
    C# 获取xml里的值
    web 点击按钮,根据点击确认进行下一步操作
    字符串宽相同
    FormClosing
  • 原文地址:https://www.cnblogs.com/muchen/p/6353777.html
Copyright © 2011-2022 走看看