`
wsql
  • 浏览: 11822916 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

自赋值是非公断

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

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


<!--内容结束//-->
分享到:
评论

相关推荐

    StyLua:固执己见的Lua代码格式化程序

    StyLua 使用构建的Lua 5.1,Lua 5.2和的公断代码格式化程序。 StyLua的灵感来自,它解析您的Lua代码库,并从头开始打印出来,以增强一致的代码样式。安装有多种安装StyLua的方法:随着Github发布预先构建的二进制...

    android手机应用源码Imsdroid语音视频通话源码.rar

    android手机应用源码Imsdroid语音视频通话源码.rar

    营销计划汇报PPT,市场品牌 推广渠道 产品 营销策略tbb.pptx

    营销计划汇报PPT,市场品牌 推广渠道 产品 营销策略tbb.pptx

    JavaScript_超过100种语言的纯Javascript OCR.zip

    JavaScript

    JavaScript_跨平台React UI包.zip

    JavaScript

    node-v16.17.0-headers.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    520表白代码.rar

    520表白html5爱心代码

    一个简单的HTML5和CSS代码示例,用于创建一个动态的爱心形状,并在网页上展示一个类似520表白的消息 这个示例使用了CSS的

    520表白html5爱心代码 一个简单的HTML5和CSS代码示例,用于创建一个动态的爱心形状,并在网页上展示一个类似520表白的消息。这个示例使用了CSS的动画效果和HTML的结构。

    智慧养老社区方案.pdf

    智慧养老社区方案.pdf

    node-v14.11.0-headers.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    JavaScript_美观和可访问的拖放列表与React.zip

    JavaScript

    codeviz 1.0.12

    codeviz 1.0.12

    JavaScript_高级用户LLM前端.zip

    JavaScript

    javascript koans是一个交互式学习环境,它使用失败测试按逻辑顺序向学生介绍javascript的各个方面.zip

    JavaScript

    JavaScript_巴勒斯坦和巴以冲突资源的策划列表.zip

    JavaScript

    JavaScript_手工制作的弗里达例子.zip

    JavaScript

    node-v17.4.0-headers.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    移动应用Android 实现QQ好友列表源码.rar

    移动应用Android 实现QQ好友列表源码.rar

    DC平台蛋白质分子匹配预测.zip

    蛋白质是生物体中普遍存在的一类重要生物大分子,由天然氨基酸通过肽键连接而成。它具有复杂的分子结构和特定的生物功能,是表达生物遗传性状的一类主要物质。 蛋白质的结构可分为四级:一级结构是组成蛋白质多肽链的线性氨基酸序列;二级结构是依靠不同氨基酸之间的C=O和N-H基团间的氢键形成的稳定结构,主要为α螺旋和β折叠;三级结构是通过多个二级结构元素在三维空间的排列所形成的一个蛋白质分子的三维结构;四级结构用于描述由不同多肽链(亚基)间相互作用形成具有功能的蛋白质复合物分子。 蛋白质在生物体内具有多种功能,包括提供能量、维持电解质平衡、信息交流、构成人的身体以及免疫等。例如,蛋白质分解可以为人体提供能量,每克蛋白质能产生4千卡的热能;血液里的蛋白质能帮助维持体内的酸碱平衡和血液的渗透压;蛋白质是组成人体器官组织的重要物质,可以修复受损的器官功能,以及维持细胞的生长和更新;蛋白质也是构成多种生理活性的物质,如免疫球蛋白,具有维持机体正常免疫功能的作用。 蛋白质的合成是指生物按照从脱氧核糖核酸(DNA)转录得到的信使核糖核酸(mRNA)上的遗传信息合成蛋白质的过程。这个过程包括氨基酸的活化、多肽链合成的起始、肽链的延长、肽链的终止和释放以及蛋白质合成后的加工修饰等步骤。 蛋白质降解是指食物中的蛋白质经过蛋白质降解酶的作用降解为多肽和氨基酸然后被人体吸收的过程。这个过程在细胞的生理活动中发挥着极其重要的作用,例如将蛋白质降解后成为小分子的氨基酸,并被循环利用;处理错误折叠的蛋白质以及多余组分,使之降解,以防机体产生错误应答。 总的来说,蛋白质是生物体内不可或缺的一类重要物质,对于维持生物体的正常生理功能具有至关重要的作用。

    二叉树的遍历代码实现.rar

    二叉树的遍历

Global site tag (gtag.js) - Google Analytics