(转)前置++和后置++的区别

 今天在阅读《google c++ 编程风格》的文档的时候,5.10. 前置自增和自减:有一句话引起了我的注意:

对于迭代器和其他模板对象使用前缀形式 (++i) 的自增, 自减运算符.,理由是 前置自增 (++i) 通常要比后置自增 (i++) 效率更高。于是我查了查前置++和后置++的区别

注意:《more effective c++》条款8也专门叙述了问题。后来我发现,下面的文章基本就是它的翻版,哈哈

前置++和后置++的区别

《C专家编程》中有如下描述(P276,人民邮电出版社):

++a表示取a的地址,增加它的内容,然后把值放在寄存器中;

a++表示取a的地址,把它的值装入寄存器,然后增加内存中的a的值;(也就是说操作的时候用到的都是寄存器里面的值,即自增前的值)

 

另外,网上找了篇文章,通过从运算符重载的角度来探讨他们的不同,如下:

 

假设有一个类Age,描述年龄。该类重载了前置++和后置++两个操作符,以实现对年龄的自增。

 

   class Age   {   public:   Age& operator++() //前置++   
        {   ++i;   return *this;   }   const Age operator++(int) //后置++   
      {   Age tmp = *this;   ++(*this);  //利用前置++   return tmp;   }   Age& operator=(int i) //赋值操作   
        {   this->i = i;   return *this;   }   private:   int i;   };

从上述代码,我们可以看出前置++和后置++,有3点不同:

  1. 返回类型不同
  2. 形参不同
  3. 代码不同
  4. 效率不同

返回值类型的区别

前置++的返回类型是Age&,后置++的返回类型const Age。这意味着,前置++返回的是左值,后置++返回的是右值。(关于左值和右值的讨论很多,见本文下面)

左值和右值,决定了前置++和后置++的用法。

    int main()   {   Age a;   (a++)++;  //编译错误   ++(a++);  //编译错误   a++ = 1;   //编译错误   (++a)++;  //OK   ++(++a);  //OK   ++a = 1;   //OK   }  

++的类型是const Age,自然不能对它进行前置++、后置++、赋值等操作。

++a的类型是Age&,当然可以对它进行前置++、后置++、赋值等操作

 

注:我们只要重载++时,只要认清前置++是没有参数的,后置++是有一个int型参数的就行了,实际调用的区分是编译器的事!

 

a++的返回类型为什么要是const对象呢?

有两个原因:

  1. 如果不是const对象,a(++)++这样的表达式就可以通过编译。但是,其效果却违反了我们的直觉 。a其实只增加了1,因为第二次自增作用在一个临时对象上。
  2. 另外,对于内置类型,(i++)++这样的表达式是不能通过编译的。自定义类型的操作符重载,应该与内置类型保持行为一致 。

a++的返回类型如果改成非const对象,肯定能通过编译,但是我们最好不要这样做。

 

++a的返回类型为什么是引用呢?

这样做的原因应该就是:与内置类型的行为保持一致。前置++返回的总是被自增的对象本身。因此,++(++a)的效果就是a被自增两次。

 

形参的区别

前置++没有形参,而后置++有一个int形参,但是该形参也没有被用到。很奇怪,难道有什么特殊的用意?

其实也没有特殊的用意,只是为了绕过语法的限制

 

前置++与后置++的操作符重载函数,函数原型必须不同。否则就违反了“重载函数必须拥有不同的函数原型”的语法规定。

虽然前置++与后置++的返回类型不同,但是返回类型不属于函数原型。为了绕过语法限制,只好给后置++增加了一个int形参。

 

原因就是这么简单,真的没其他特殊用意。其实,给前置++增加形参也可以;增加一个double形参而不是int形参,也可以。只是,当时就这么决定了。

 

代码实现的区别

前置++的实现比较简单,自增之后,将*this返回即可。需要注意的是,一定要返回*this。

后置++的实现稍微麻烦一些。因为要返回自增之前的对象,所以先将对象拷贝一份,再进行自增,最后返回那个拷贝。

 

在Age的代码中,后置++利用了前置++来实现自增。这样做是为了避免“自增的代码”重复。

在本例中,自增的代码很简单,就是一行++i,没有必要这样做。但是在其它自增逻辑复杂的例子中,这么做还是很有必要的。

 

效率的区别

如果不需要返回自增之前的值,那么前置++和后置++的计算效果都一样。但是,我们仍然应该优先使用前置++,尤其是对于用户自定义类型的自增操作。

前置++的效率更高,理由是:后置++会生成临时对象。

 

从Age的后置++的代码实现也可以看出这一点。    

    const Age operator++(int) //后置++   
    {   Age tmp = *this;   ++(*this);  //利用前置++   return tmp;   }  

很明显,tmp是一个临时对象,会造成一次构造函数和一次析构函数的额外开销。虽然,编译器在某些情况下可以优化掉这些开销。但是,我们最好不要依赖编译器的行为。


所以,在非内置类型的时候,尽量使用前置++,因为效率高(后置自增,效率低)

 

原文链接:http://blog.csdn.net/randyjiawenjie/article/details/6747720

转载于:https://www.cnblogs.com/balingybj/p/4736195.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/296636.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一起谈.NET技术,异步调用与多线程的区别

随着拥有多个硬线程CPU(超线程、双核)的普及,多线程和异步操作等并发程序设计方法也受到了更多的关注和讨论。本文主要是想探讨一下如何使用并发来最大化程序的性能。 多线程和异步操作的异同 多线程和异步操作两者都可以达到避免调用线程阻塞…

中国最美街景,带你一次看个够

全世界只有3.14 % 的人关注了爆炸吧知识生活永远比电视剧精彩,真正的美景永远比图片美!中国960万平方公里的土地上,拥有无穷无尽的美景,足以将你的眼睛搁在天堂。抛开那些耳熟能详的景区不谈,单单是一些普通街道&#…

6计算机系统的组成是,计算机系统的组成(范文)(6页)-原创力文档

第 PAGE \* Arabic 1 页计算机系统的组成(范文)PAGE计算机系统的组成一、教学目标:知识与技能:⑴ 学生了解计算机组成各部分的名称和作用。⑵ 学生知道计算机的硬件有哪些。⑶ 学生知道什么是计算机软件,了解计算机软件的作用。⑷ 通过介绍国…

[031] 实战:书大师网站开发准备

.NET大牛之路 • 王亮精致码农 • 2021.10.19前面我们花了二十篇左右的文章讲 C# 基础和高级知识点。由于后面要讲的东西还有很多,所以 C# 的内容没办法做到讲得细而全,只能走马观花一扫而过。在后面的内容中如果有遇到 C# 高级知识点,我们再…

计算机视觉招聘_INDEMIND|SLAM、计算机视觉、深度学习算法招聘(社招实习)

公司介绍INDEMIND是一家专注于计算机视觉技术研发与嵌入式计算平台研发的人工智能公司,行业领先的计算机视觉方案提供商。公司成立于2017年,核心技术团队成员均为来自计算机视觉领域的顶级技术人员。研发团队结合自身在计算机视觉技术上的优势&#xff0…

2012暑假最后两次组队赛总结

最后两次组队赛的题都相对简单,所以两次都得到较高的题目数!一次是在hdu的diy上做,另外的是在bnu做spoj的题。先补回倒数第二场的总结。倒数第二场一共有10题,当时过的题包括一题枚举求最大值,一题二分求概率&#xff…

依赖Zookeeper生成全局唯一序列号

下面2张图来自:http://www.open-open.com/doc/view/2e0a82e0081d489dace301a2c512053c 关于Zookeeper服务安装,配置,启动, 客户端操作参见:http://aiilive.blog.51cto.com/1925756/1684451 http://aiilive.blog.51cto.com/1925756…

小眼睛有多惨?美颜都懒得救你......

1 眼睛小的人系统一般会自动识别为没睁开▼2 你想笑死我吧???▼3 大家都是狗,凭什么???▼4 这鱼是怎么跳上来的?▼5 感觉有被冒犯到▼6 这个车贴太可爱了!▼7 君子…

软件开发了10年,迷茫了

在新疆做了10年软件开发,从asp开始不断学习,每出现一个新技术自己都会夜以继日的学习,总以为这个技术会是潮流,会持续几年,但结果是不到两年就已经落伍。身边的人慢慢的离开了软件开发队伍,终于2年前自己也…

jmeter聚个报告怎么看qps_Jmeter 使用笔记之 html 报告扩展(一)

题记:在用 loadrunner 的时候可以生成一个 HTML 的报告,并且里面包含各种图表,各种详细的数据。而在使用 Jmeter 测试完后并不能直接生成 Html 的报告(无论是用 GUI 还是命令行启动)。经过查找资料发现 Jmeter 的 extras 目录下有生成 HTML 的…

.NET网站国际化策略

我所在的公司是做SAAS软件,用户群体是面向全球的,因此对应业务系统国际化就是顺理成章的事情。其实国际化重点在于多语言支持,本文就从这方面入手。多语言如上解决方案截图,BQoolCommon.Resource是多语言资源工程,下面…

将数字转化为液晶显示屏的样子

发一个很蛋疼的程序&#xff0c;将一个数字转化为液晶显示屏显示的样子&#xff1a;第一个输入是尺寸&#xff0c;第二输入是要转化的数字&#xff0c;当两个参数都为0的时候结束输入&#xff1a; #include<iostream> using namespace std;struct Print{int size;int num…

计算机标准符合,计算机专利申请要符合哪些标准

需要具体分析&#xff0c;例如&#xff0c;外观专利申请流程&#xff1a;&#xff11;、外观设计专利申请受理阶段专利局收到专利申请后进行审查&#xff0c;如果符合受理条件&#xff0c;专利局将确定申请日&#xff0c;给予申请号&#xff0c;并且核实过文件清单后&#xff0…

史上最强电池!三位诺贝尔奖获奖者研究了大半辈子,却坦言还是没看懂?

全世界只有3.14 % 的人关注了爆炸吧知识手机患了忧郁症电量总剩1%晚上十点半了&#xff0c;还剩10%的电量&#xff0c;等我用完这些电就睡觉..5%了&#xff0c;这个推文看完应该就没电了1%了&#xff0c;算了再看一个&#xff0c;还没关机呢看完了&#xff0c;还是1%&#xff0…

libgdx 学习笔记七 libgdx应用程序生命周期

简介 本章内容描述libGDX 应用程序的结构和怎么根据不同的平台版本使用不同的后台 The Application 做为任意libGDX 工程的主入口点。Application 决定平台的版本和后台图形。Application 接口提供了合适的方法来访问Graphics, Audio, Input and File I/O模块。也提供了跨平台的…

工业相机与民用相机的区别_工业相机和普通相机的区别详解

在机器视觉迅猛发展的今天&#xff0c;工业相机作为机器视觉的核心组件已得到广泛应用&#xff0c;但是很多初学者还是搞不清楚究竟工业相机与普通相机有什么区别。下面小编就带大家一起去看看工业相机和普通相机的区别吧&#xff01;工业相机一、工业相机和普通相机的区别之性…

50个Android应用!Win11支持运行了

文 | 局长出品 | OSC开源社区&#xff08;ID&#xff1a;oschina2013&#xff09;Android 应用现已支持在 Windows 11 上运行。微软今日宣布&#xff0c;美国地区 Windows 11 Beta 通道的预览版已支持运行 Android 应用。正如公告所说&#xff0c;如需体验在 Windows 11 上运行…

javascript规范以及设计原则

UI layer的分离 针对CSS: 尽量不要在JS中的添加过多的动态CSS&#xff0c;可以考虑使用addClass 针对JS中的事件&#xff1a; Keep JavaScript Out of HTML 避免以下的代码 <!-- Bad --><button οnclick"doSomething()" id"action-btn">Click…

服务器的类型及作用是什么,按用途分类,服务器有哪些? - 问答库

问题&#xff1a;[问答题] 按用途分类&#xff0c;服务器有哪些&#xff1f;某工程包含两个单项工程&#xff0c;分别发包给甲、乙两个承包商。在施工中发生如下事件。事件一&#xff1a;该工程签约时的计算工程价款为1000万元&#xff0c;该工程固定要素的系数为0.2&#xff1…

删除

【题目描述】 现在&#xff0c;我的 上有 n 个数字&#xff0c;分别是 a1; a2; a3; :::; an。 我现在需要删除其中的 k 个数字。当然我不希望随随便便删除&#xff0c;我希望删除 k 数字之后&#xff0c;剩下的 n k 个数中有最多的不同的数 【输入格式】 第 两个正整数 n 和 …