博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Thinking again in C++(二)自赋值是非公断 (转)
阅读量:2499 次
发布时间:2019-05-11

本文共 2390 字,大约阅读时间需要 7 分钟。

Thinking again in C++(二)自赋值是非公断 (转)[@more@]

  爱死Thinking in系列了,所以起了这个名字。本文的思想也部分来至于这套书,或参照对比,或深入挖掘,或补益拾慧,或有感而发,既包括Thinking in C++,甚至也包括Thinking in 。

  Thinking again in C++(二)自赋值是非公断

  关键字:C++,自赋值,自复制,赋值,assign,assignment,复制,拷贝,copy

  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%,这在实际代码中可能吗?

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10748419/viewspace-982478/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/10748419/viewspace-982478/

你可能感兴趣的文章
xshell配色
查看>>
php缓存
查看>>
绘制文本
查看>>
多表查询SQL99
查看>>
主元素问题(Java)
查看>>
不同版本的Eclipse安装SVN插件
查看>>
Windows下的cmd命令行中设置环境编码
查看>>
POJ 3557 Map Generator
查看>>
转:Linux环境下段错误的产生原因及调试方法小结
查看>>
Coursera, Deep Learning 1, Neural Networks and Deep Learning - week1, Introduction to deep learning
查看>>
《mysql 必知必会》 笔记(六)
查看>>
Python 函数
查看>>
EasyUI表格datagrid合并行单元格
查看>>
云时代架构阅读笔记一——Java性能优化(一)
查看>>
7.15-7.21第三周周进度报告
查看>>
(hdu step 8.1.2)Train Problem I(站的基本应用——推断一个序列经过栈后是否可以得到第二个序列)...
查看>>
aptitude约等于apt-get的工具
查看>>
PHP反序列化漏洞
查看>>
红尘来去一场梦
查看>>
cf16E Fish(状压DP)
查看>>