文档章节

在循环语句中,for(i=0;i<n;i++)和for(i=0;i<n;++i)有什么区别?

geek_loser
 geek_loser
发布于 2016/11/03 13:03
字数 2585
阅读 1638
收藏 0

程序员 代码 C(编程语言) C++ C / C++

在循环语句中,for(i=0;i<n;i++)和for(i=0;i<n;++i)有什么区别?

我同学有简单地告诉我,i++的话要先copy出一个i然后赋值,用原来的i继续其他运算,最后再把copy出来的i做个increment,然后返还给原来的i。
而++i直接在原来的i上做increment。
结论:当n很大的时候,++i速度比i++快。

比如语法上a = i++; 是等号右边的变量赋值给左边的变量,但是赋值应发生在所有运算之后。这就比较矛盾,如果用上诉理论就能解释得清楚。

请问他说的对吗?

3 条评论

按时间排序 默认排序

17 个回答

知乎用户 时刻都要保持优雅

这个问题把我们送回了80年代那个勒紧裤腰带开发程序的日子,多两三条代码程序会慢到死吗,我相信现在已经不是主要问题了,就算出现问题,那也是编译器作者的问题,不是程序员的问题。

编辑于 2015-06-07 添加评论 感谢

收藏没有帮助举报 作者保留权利

隼之心 活着就是最好的

1 人赞同

只是人的习惯问题,就好比为什么每个语言第一个程序叫hello world而不是hello monkey

发布于 2015-05-15 添加评论 感谢

收藏没有帮助举报 作者保留权利

Yi Zhao 资深学渣

1 人赞同

加一段timer不就知道了么,我只记得老师说不管是++i还是i++都比i=i+1快,i++在n十分大的时候慢于++i,原理早忘了(或许应该查看下汇编)

发布于 2015-05-13 1 条评论 感谢

收藏没有帮助举报 作者保留权利

宁绪 灵魂黑客兼画师,以前曾是一名Android De…

2 人赞同

学校里就讲到++i先将i加一再运算,i++把原值运算后再加一,好low,突然感觉。。。。。。

发布于 2015-05-11 添加评论 感谢

收藏没有帮助举报 作者保留权利

嘛咪嘛咪哄 软件工程师,喜自由自在,趣味广

1 人赞同

测试一下

发布于 2015-05-11 添加评论 感谢

收藏没有帮助举报 作者保留权利

徐辰 C++ is nothing about OOP

1 人赞同

在C++里,假如i是int,那么没有任何不同,无论开不开优化,你没有使用自增后的i值,编译器根本就不会“复制”一个i。
如果i是个自定义类型,又自定义了前缀和后缀++操作符,那自然是不一样的。

发布于 2015-05-11 添加评论 感谢

收藏没有帮助举报 作者保留权利

知乎用户 都看到这里了,关注一下吧。

2 人赞同

本来,这样的问题我不会回答,心里说“编译器君掩面不语”后跳到下一个问题。
但是冲着你的第一句话:“(这个问题估计1万个程序员也不到1个能真正领悟)”。我忍不住进来跟你说,同学,你一定要成为一个万里挑一的程序员啊。

编辑于 2015-05-13 4 条评论 感谢

收藏没有帮助举报 作者保留权利

Gomo Psivarh 码见 / RetroGame / 日麻 / LoveLive

24 人赞同

我想说的是现在已经是2015年了,编译器都发展了几十年了连这点优化都做不到也好意思拿得出来?程序优化的重点应该放在项目的性能瓶颈上,而不是抠这种几乎无意义的细枝末节。

再说了,如果你非觉得编译器不可信非要写成++i,那我可以告诉你把

for(int i=0; i<n; ++i)

写成

for(int i=n-1; i>=0; --i)

会更快(汇编可以少一个CMP指令,当然主流的编译器基本都会自动帮你做这样的优化)

你会把程序中所有循环改成下面那种吗?

编辑于 2015-05-11 2 条评论 感谢

收藏没有帮助举报 作者保留权利

知乎用户 计算机吐槽学

2 人赞同

按C来说
i++把i增加1,返回i增加前的值
至于是先计算整个表达式还是先增加i应该是未定义的
++i先把i加1,返回i的引用
在for里i++和++i由于返回值没有被使用,因此会被优化成一样的结果

发布于 2015-05-11 1 条评论 感谢

收藏没有帮助举报 作者保留权利

孙明琦 会用几门语言写helloworld

11 人赞同

不开优化,并没有什么不同
开启优化,编译器是不会在这种地方拖慢你的程序的
能把循环内的乘法优化成两个add指令,循环本身的跳转也大大简化
优化之后的代码已经看不到所谓的i++和++i了
(哪位聚聚能给解释一下那两个add指令是如何变成乘法的)


有些人就是不肯平心静气地和人说话,是吧

编辑于 2015-05-11 25 条评论 感谢

收藏没有帮助举报 作者保留权利

Merci飞来飞去 王阳明

1 人赞同

i++返回的是i本身的值,++i返回的是i+1的值,可以写一个小程序测试一下就知道了。

发布于 2015-05-11 1 条评论 感谢

收藏没有帮助举报 作者保留权利

颢凡 再浪一年

1 人赞同

for循环中不好说明,不妨假设有这样一个表达式:
int i = 3;
int k;
k = ++i; //#1
k = i++; //#2

前置递增运算符:对象递增加一再使用

即:
/* #1等价于 */
i = i+1; //i的值为4
k = i; //k 的值为4

后置递增运算符:创建一个临时对象,将临时对象替换调用原变量的位置,原变量+1

即:
/* #2等价于 */
k = int(i); //int(i) 是一个临时对象,值为4
i = i+1; //i 的值为5

也就是说后置递增相比前置递增会创建一个临时对象int(i),使用临时对象赋值给k,所以后置递增会比前置递增慢那么一丢丢。

发布于 2015-05-11 添加评论 感谢

收藏没有帮助举报 作者保留权利

知乎用户 德国队/拜仁粉/幼儿期码农

2 人赞同

习惯用++i,但我相信编译器对此的优化,不会在意它的性能。

对于a = i++;那段,我不大清楚你的问题,不知道下面这样说能不能帮你理解。

你说的“等号右边的变量赋值给左边的变量”,那既然是“值”,这个值也就可以来自于另外一个变量(假设是t),t保存了i自增前的值,然后把t返回给了左边进行赋值操作。

把++理解成下面这个方法。

int jiajia(int &i)
{
    int t = i;
    i += 1;
    return t;
}


a = i++;就变成了a = jiajia(i);

发布于 2015-05-11 2 条评论 感谢

收藏没有帮助举报 作者保留权利

panszAndroid 开发、Linux话题优秀回答者 我说的大多是一…

39 人赞同

如果 i 是系统类型,两者没有性能区别。绝大多数编译器可以生成同效率代码。由于所谓的多余复制的变量并没有被用到(i++的返回值无人使用),所以编译器优化之后跟++i等价。

两者性能区别理论上存在于当 i 是一个自定义的类,并且这个类重载了++操作符,并且这个类重载「后增量」操作符时使用了值复制作为返回值的情况,在这种情况下,有时编译器能优化掉多余的复制,有时不能。所以++对于自定义对象类型来说会有题主所说的情况。

编辑于 2015-09-19 4 条评论 感谢

收藏没有帮助举报 作者保留权利

毛草 软件工程师/MBA在读/考虑创业/动漫宅/单…

所有支持++的语言中,按定义++i的速度一定大于等于i++

发布于 2015-05-11 3 条评论 感谢

收藏没有帮助举报 作者保留权利

薛非 《品悟C》作者

7 人赞同

在循环语句中,for(i=0;i<n;i++)和for(i=0;i<n;++i)有什么区别?

没。

我同学有简单地告诉我,i++的话要先copy出一个i然后赋值,用原来的i继续其他运算,最后再把copy出来的i做个increment,然后返还给原来的i。
而++i直接在原来的i上做increment。

无依据的臆测。

比如语法上a = i++; 是等号右边的变量赋值给左边的变量,但是赋值应发生在所有运算之后。

错。

====================================

做点正事,不要问没有意义的问题。

现代程序设计不怎么追求速度,通常认为代码可读性优先于程序效率。

即使要求效率也是从算法和数据结构入手,

从for语句中挖掘速度无异于从牙缝里找吃的希望吃的更饱些。

编辑于 2015-05-11 11 条评论 感谢

收藏没有帮助举报 作者保留权利

Intopass Java Developer Learning C++

11 人赞同

一:i++ 和 ++i
从Java的角度来说,这两个没有区别。(证据,生成的字节码一样。)
从C/C++的角度来说,++i可能更好一些,因为不用存储一个中间变量。(但我怀疑这个是可以被编译器优化掉的。)
二:运算顺序
讨论一个语句中如,i = i++ + i++。究竟++操作是何时发生的,对于C/C++语言可能没有意义,因为是未定义行为,对于Java来说是有意义,因为Java明确定义了运算顺序。

编辑于 2015-05-11 10 条评论 感谢

收藏没有帮助举报 作者保留权利

本文转载自:https://www.zhihu.com/question/30267881?sort=created

geek_loser
粉丝 3
博文 74
码字总数 18849
作品 0
朝阳
私信 提问
i++循环与i--循环

在网上看到一篇文章,里面说i++和i--的效率有区别,这个区别我早就知道,其实就是一个标志寄存器的重用问题,虽然早就知道还是想写出来来展示一下计算的魅力,这两个例子是: int loop_dec(i...

晨曦之光
2012/04/10
139
0
【语法篇】4、for循环(一)

一、循环 大部分人孩提时的数学启蒙都是从数数开始的,如果要我们编程让计算机从1数到10,我们用输出来替代数数,即是要将1到10依次打印出来,我们可以怎么实现呢?这当然很简单了,我们最直...

沧海无雨
2017/09/25
0
0
我来理解for循环

简单示例 先看一段简单的代码: 这段代码的含义是什么?求和:sum = 1 + 2 + 3 + .. + n,当前n为5。 这段代码是怎么执行呢? 声明sum,,并赋值0。(int sum = 0) 声明n,赋值为5。(int n...

艳沐石
2016/12/28
17
0
C#语法入门

1、大小写区别 2、在C#中的布尔类型为bool,而JAVA为boolean 3、C#有一个不安全模式,在此模式之下可以使用指针 4、有枚举类型 5、代理和索引器 6、运算符重载 7、没有throws关键字 下面开始...

晨曦之光
2012/03/09
173
0
OpenMP并行程序设计——for循环并行化详解

这篇OpenMP的for循环使用已经很详尽了,而且例子很好,就转载了,不再自己另开篇博客。 感谢作者。 转载请声明出处http://blog.csdn.net/zhongkejingwang/article/details/40018735 在C/C++...

sirius_0
2018/04/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

聊聊Elasticsearch的CircuitBreakerService

序 本文主要研究一下Elasticsearch的CircuitBreakerService CircuitBreakerService elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/indices/breaker/CircuitBreakerService.ja......

go4it
32分钟前
3
0
Spring系列教程六:AOP详细讲解

AOP 概述 什么是 AOP AOP:全称是 Aspect Oriented Programming 即:面向切面编程。 AOP技术是对OOP技术的一种延伸,AOP是面向纵向,OOP是面向横向。简单的说它就是把我们程序重复的代码抽取...

我叫小糖主
45分钟前
12
0
Qt编写数据可视化大屏界面电子看板9-曲线效果

一、前言 为了编写数据可视化大屏界面电子看板系统,为了能够兼容Qt4和嵌入式linux系统,尤其是那种主频很低的,但是老板又需要在这种硬件上(比如树莓派、香橙派、全志H3、imx6)展示这么华...

飞扬青云
今天
3
0
责任链模式

//这篇博客的博主真的不错,解析的都很清晰明了, https://blog.csdn.net/jason0539/article/details/45091639

南桥北木
今天
3
0
Flutter -------- dio网络请求

dio是Flutter中文网开源的一个强大的Dart Http请求库,支持Restful API、FormData、拦截器、请求取消、Cookie管理、文件上传/下载、超时等... 1.添加依赖# dependencies: dio: 2.1.x #...

切切歆语
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部