[转]C++的自赋值问题

原创 2007年10月07日 15:56:00

再用到操作符重载的时候,注意到了这个问题

如果不进行自我赋值检查。就有可能出现一种情况。那是灾难性的。举例说。你在拆房子。如果你不先看看自己是否在房子里就直接拆了。那会是怎么样呢??想想就知道。

在网上搜索了一下,转载一个现成的:http://www.lough.com.cn/cpp/thincpp2.htm

1.需要考虑的自赋值。当类包含指针或引用成员时应注意检查。
      class String
      {
      private:
            char * pc_Buffer;
      public:
            String & operator=(const String & strR);
            String & operator+=(const String & strR);
            //...
      };
      
    (1)类内部:对称赋值运算符、接受自身类型或自身基类类型参数的成员
函数,有时候还要考虑+=系列运算符。

      String & String::operator=(const String & strR)
      {
            if (this==&strR)      //[1]
                  return *this;
            delete [] pc_Buffer;      //[2]
            pc_Buffer=new char[strlen(strR.pc_Buffer)+1];//[3]
            //...
      }
      
    [1] 中的判断是必须的。如果this==&strR ,[2] 将本身删除,[3] 就会使
用“悬挂指针”。

    下面operator+=()的实现隐藏着错误。
      String & String::operator+=(const String & strR)
      {
            int iLengthNew=strlen(pc_Buffer)+strlen(strR.pc_Buffer);
            char * pcBufferNew=new char[iLengthNew+1];
            strcpy(pcBufferNew,pc_Buffer);
            delete [] pc_Buffer;                  //[4]
            strcat(pcBufferNew,strR.pc_Buffer);      //[5]
            pc_Buffer=pcBufferNew;
            return *this;
      }
      
    如果this==&strR ,[4] 将本身删除,[5] 就会使用“悬挂指针”。正确的
做法不必使用判断语句,只需调换[4][5]两条语句的顺序。

    (2 )类外部(包括友元):接受多个同一类型参数或多个有继承关系的类
型参数的函数。

      class CDerive : public CBase{};
      void f(CBase & b1,CBase & b2);
      void g(CBase & b,CDerive & d);
      CBase bSame;
      CDerive dSame;
      f(bSame,bSame);            //[1]
      f(dSame,dSame);            //[2]
      g(dSame,dSame);            //[3]
    [1][2][3]都出现了自赋值,所以f()、g()的设计中都要有所考虑。

    2.不可能出现自赋值。

    (1 )拷贝构造器:因为正在构造的对象还未完全生成,而传递给构造器的
实参对象是已构造完毕的对象,这两者绝不可能是同一对象。

    (2 )非对称赋值运算符:即使形参类型是自身的基类。若D 是B 的派生类,
无论是否重载了对称赋值运算符,D 类对象之间的赋值行为都不会调用
D::operator=(const B& b)。

      class CDerive : public CBase
      {
      public:
            operator=(const CBase & b);   //不用考虑this和b之间的自赋值
            void f(const CBase & b);      //需要考虑this和b之间的自赋值
      };
      CDerive dSame;
      dSame=dSame;            //[1]
      dSame.f(dSame);            //[2]
      
    语句[1] 中,编译器不会把dSame 上溯造型为CBase ,而是调用缺省或自定
义的D ::operator= (const D & d )。只有等式左边确为D ,右边确为B ,
才调用D ::operator= (const B & b ),这时不可能出现自赋值。相反,语
句[2] 中,编译器会把dSame 上溯造型为CBase ,所以f ()需要考虑自赋值。


    3.不是自赋值的赋值。仅仅内容相同的赋值不是自赋值。
    
      CTest a,b,same;
      a=same;
      b=same;
      a=b;      //[1]
      
    [1] 不是自赋值,不会出问题,不需要检查,而且内容相同无法直接用地址
来检查。

    4.不应该检查的自赋值。
    
    strcpy(char * strDest,const char * strSrc );中,当strDest==strSrc
时,是自赋值,但并不会出错。

    发现自赋值直接返回,这种特定情况下,也许能提高函数效率10倍,但绝大
多数没有出现自赋值时都多了一个条件判断,可能降低函数效率10% ,最后综合
计算加权平均效率可能还是降低了。这取决于自赋值出现的概率。

    设不判断自赋值,函数执行时间为1 ;若检查自赋值,设出现自赋值的概率
为x ,直接返回函数执行时间为0.1 ,不出现自赋值,多了一个条件判断函数执
行时间为1.1 ,那么如果要求加权平均效率不降低:
      0.1x+1.1(1-x)<1
    解之,得:x>0.1.也就是说自赋值出现的概率必须大于10% ,这在实际代码
中可能吗?

 

C++的自赋值问题

再用到操作符重载的时候,注意到了这个问题 如果不进行自我赋值检查。就有可能出现一种情况。那是灾难性的。举例说。你在拆房子。如果你不先看看自己是否在房子里就直接拆了。那会是怎么样呢??想想就知道。...
  • OutManLee
  • OutManLee
  • 2012年03月13日 18:59
  • 1560

C++ 重载运算符“=”检测自赋值

重载赋值运算符 赋值运算符可能是最容易令人迷惑的一个,所以,重载它必须十分的小心。 1. 值运算符仅能重载为成员函数。  C++不允许赋值运算符被重载为全局形式,这是因为如果可以写出...
  • wo17fang
  • wo17fang
  • 2014年08月12日 10:40
  • 631

为什么赋值运算符要防止自身赋值

为什么赋值运算符要防止自身赋值呢?? 如果类里面含有指针指向动态分配的资源的话,那么自身赋值就可能出错 有可能导致把自己给释放了 如下面: #include #i...
  • u012501262
  • u012501262
  • 2014年03月29日 15:41
  • 769

C++ 前自增和后自增

http://topic.csdn.net/u/20100331/22/d5513158-3d0e-4ac8-9ea7-f59916d3d2eb.html 在C++中,前自增操作生成左值,后自增...
  • IEEEITU
  • IEEEITU
  • 2011年09月03日 10:38
  • 2425

c++ 中 char 与 string 之间的相互转换问题

第一部分: 将  char *    或者    char []   转换为  string 可以直接赋值,转换。       第二部分: 将   string   转换为 ch...
  • pql925
  • pql925
  • 2017年04月09日 13:20
  • 1053

C++结构体数组赋值问题

说明:以下是在网上找到的对结构体中数组赋值问题的总结,感觉可以就复制过来了结构体中字符串数组的赋值问题2007年10月15日 星期一 15:33在使用结构体时,每当遇到字符串数组时总是容易出项问题:好...
  • doudou1314
  • doudou1314
  • 2010年04月13日 11:38
  • 5361

C++中char*和LPCTSTR类型的转化

转换方式有两种: 第一,如果是在MFC中,可以利用CString直接转。这种方式很简单网上也很多不做说明。 第二,非MFC程序。 因为普通C++代码中没有CString类型,所以不能直接运用CS...
  • maqianQAQ
  • maqianQAQ
  • 2016年11月01日 14:16
  • 2030

c++自增自减运算汇总(经典)

c++自增自減問題  在程序设计中,经常遇到“i=i+1”和“i=i-1”这两种极为常用的操作。变量i被称为“计数器”,用来记录完成某一操作的次数。C语言为这种计数器操作提供了两个更为简洁的运算符,...
  • THISISPAN
  • THISISPAN
  • 2012年04月10日 18:12
  • 9914

关于自增和赋值的运算

a=i++   等价于  先执行a=i然后再运算i++    但自增的运算优先级比赋值要高,不应该是  先运算i++然后再执行a=i吗...
  • qq_40660787
  • qq_40660787
  • 2017年11月01日 17:42
  • 125

c/c++赋值“=”返回值问题

以前一直以为赋值语句返回的是一个bool, 好吧我错了,直到看到这道迅雷的笔试题 for(int i=10, j=1; i=j=0; i++, j--)() A...
  • z1002137615
  • z1002137615
  • 2015年09月30日 15:28
  • 344
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[转]C++的自赋值问题
举报原因:
原因补充:

(最多只允许输入30个字)