关于for(),为什么使用i ++而不是++ i?

时间:2010-10-06 17:51:21

标签: java php c++ c

一旦优化它可能对编译器无关紧要,但在C / C ++中,我看到大多数人以以下形式进行for循环:

for (i = 0; i < arr.length; i++)

使用post fix ++完成递增。我得到了两种形式之间的区别。 i ++返回i的当前值,但是在安静时将i加1。 ++我首先将i加1,然后返回新值(比我多1)。

我认为i ++需要更多的工作,因为除了下一个值之外还需要存储先前的值:Push *(&amp; i)to stack(或load to register);增量*(&amp; i)。 Versus ++ i:增量*(&amp; i);然后根据需要使用*(&amp; i)。

(我得知“递增*(&amp; i)”操作可能涉及寄存器加载,具体取决于CPU设计。在这种情况下,i ++需要另一个寄存器或堆栈推送。)

无论如何,在什么时候,为什么,i ++变得更时尚?


我倾向于相信azheglov:这是一个教育学的东西,因为我们大多数人在Window或* nix系统上进行C / C ++编译器的高质量,没有人受伤。

如果您使用的是低质量编译器或解释环境,则可能需要对此敏感。当然,如果你正在进行高级C ++或设备驱动程序或嵌入式工作,希望你已经足够经验丰富,这根本不是什么大问题。 (狗是否具有佛性?谁真的需要知道?)

13 个答案:

答案 0 :(得分:10)

使用哪个并不重要。在一些极其过时的机器上,在某些使用C ++的情况下,++i效率更高,但现代编译器如果没有存储则不存储结果。至于for循环中的帖子开始变得流行的时候,我的K&amp; R第二版副本使用了第65页的i++(我在翻阅时找到的第一个for循环。)< / p>

答案 1 :(得分:5)

出于某种原因,i++在C中变为 更具惯用性 ,即使 它会创建一个不必要的副本 < / strong>即可。 (我认为这是通过K&amp; R,但我认为这在其他答案中有争议。)但我不认为C中存在性能差异,它只用于内置函数,编译器可以 优化复制操作

但它确实在C ++中有所作为,i可能是operator++()重载的用户定义类型。编译器可能无法断言复制操作没有可见的副作用,因此可能无法消除它。

答案 2 :(得分:4)

至于原因,这就是K&amp; R在这个问题上所说的话:

Brian Kernighan

  

你必须问丹尼斯(它可能在HOPL paper)。我有一个   昏暗的记忆,它与后期增量操作有关   pdp-11虽然超出了我不知道的范围,所以不要引用我。

     

在c ++中,迭代器的首选样式实际上是++ i的一些细微之处   实施原因。

Dennis Ritchie

  

没有特别的原因,它只是变得时髦。代码产生了   在PDP-11上是相同的,只是一个inc指令,没有自动增量。

HOPL论文

  汤普森通过发明增加或减少的++和 - 运算符更进了一步;它们的前缀或后缀位置确定更改是在注意操作数的值之前还是之后发生。它们不是最早版本的B,而是沿途出现。人们经常猜测它们是为了使用DEC PDP-11提供的自动递增和自动递减地址模式而创建的,C和Unix最初开始流行。这在历史上是不可能的,因为在开发B时没有PDP-11。然而,PDP-7确实有一些“自动增量”存储器单元,其特性是通过它们的间接存储器引用增加了单元。这个功能可能会向Thompson建议这样的操作员;使它们成为前缀和后缀的概括是他自己的。实际上,自动增量单元并没有直接用于运算符的实现,而是更强大   创新的动机可能是他观察到++ x的翻译小于x = x + 1的翻译。

答案 3 :(得分:3)

对于整数类型,当您不使用表达式的值时,两个表单应该是等效的。在具有更复杂类型的C ++世界中,这已不再适用,但保留在语言名称中。

我怀疑“i ++”在早期变得更受欢迎,因为这是原版K&amp; R“The C Programming Language”一书中使用的风格。你必须问他们为什么选择这种变体。

答案 4 :(得分:3)

因为一旦你开始使用“++ i”,人们就会感到困惑和好奇。他们将停止日常工作并开始谷歌搜索解释。 12分钟后,他们将进入堆栈溢出并创建一个这样的问题。瞧,你的雇主只花了10美元

答案 5 :(得分:2)

比K&amp; R更进一步,我看了它的前身:Kernighan's C tutorial(〜1975)。这里的前几个while示例使用++n。但是每个for循环都使用i++。所以回答你的问题:几乎从一开始就i++变得更加时髦。

答案 6 :(得分:1)

我认为随着C ++的创建,它变得更加时髦,因为C ++使你能够在非平凡的对象上调用++。

好的,我详细说明:如果你调用i++并且i是一个非平凡的对象,那么在增量之前存储包含i值的副本将比指针更昂贵或整数。

答案 7 :(得分:1)

在某种程度上,它是惯用的C代码。这就是通常的事情。如果那是你的巨大性能瓶颈,你可能会遇到一个独特的问题。

然而,看看我的K&amp; R C编程语言,第1版,我在循环中找到的第一个实例(第38页)确实使用++ i而不是i ++。 / p>

答案 8 :(得分:1)

我的理论(为什么i ++更流行)是当人们学习C(或C ++)时,他们最终会学习如下代码迭代:

while( *p++ ) {
    ...
}

请注意,修复后的表单在这里很重要(使用中缀表单会创建一次性类型的错误)。

当需要编写for循环时,++ii++并不重要,使用后缀形式可能会更自然。

ADDED:我上面写的内容确实适用于原始类型。在使用原始类型编写代码时,您倾向于快速地执行操作并自然地执行操作。这是我需要依附于我的理论的重要警告。

如果++是C ++类的重载运算符(Rich K.在评论中建议的可能性),那么当然你需要非常谨慎地编写涉及这些类的循环,而不是做一些简单的事情。自然。

答案 9 :(得分:0)

我认为我的前任对于选择增加后增量的副作用是正确的。

因为它的时尚性,它可能就像你在for语句中以相同的重复方式开始所有三个表达式一样简单,这是人类大脑似乎倾向于的东西。

答案 10 :(得分:0)

我会加上其他人告诉你的主要规则是:保持一致。选择一个,除非是特定情况,否则不要使用另一个。

答案 11 :(得分:0)

如果循环太长,则需要重新加载缓存中的值以在跳转到开始之前递增它。 你不需要++ i,没有缓存移动。

答案 12 :(得分:0)

在C中,除了前缀inc / dec之外,所有导致变量具有新值的运算符都会修改左手变量(i = 2,i + = 5等)。因此,在++ i和i ++可以互换的情况下,许多人对i ++更加满意,因为操作员在右侧,修改左手变量

如果第一句话不正确,请告诉我,我不是C的专家。