递增:x++ 与 x += 1
Posted
技术标签:
【中文标题】递增:x++ 与 x += 1【英文标题】:Incrementing: x++ vs x += 1 【发布时间】:2011-09-24 11:31:54 【问题描述】:我读到许多开发人员使用 x += 1 代替 x++ 以清楚起见。我知道 x++ 对新开发人员来说可能是模棱两可的,而 x += 1 总是更清楚,但是两者之间的效率有什么区别吗?
使用 for 循环的示例:
for(x = 0; x < 1000; x += 1)
与 for(x = 0; x < 1000; x++)
我知道这通常没什么大不了的,但如果我反复调用执行这种循环的函数,从长远来看可能会累加。
另一个例子:
while(x < 1000)
someArray[x];
x += 1;
对
while(x < 1000)
someArray[x++];
可以将 x++ 替换为 x += 1 而不会造成任何性能损失吗?我特别担心第二个示例,因为我使用的是两行而不是一行。
如何增加数组中的项目?在大循环中完成时,someArray[i]++
会比 someArray[i] += 1
更快吗?
【问题讨论】:
您可以通过运行基准测试来发现这一点! 根据您使用的任何语言,编译器很可能会为两个语句生成相同的代码。 过早的优化是万恶之源。 为了后代,我更喜欢x++
到x += 1
我相信你后面的例子有两个不同的陈述。在第一个中,您访问数组 someArray 的索引 x,然后将 x 增加 1。在第二个中,您访问数组 someArray 的索引 x+1。
@YGomez:不,x++
先返回x
,然后再增加。
是的,但我必须测试每种语言。我想知道是否有一些我可以遵循的经验法则。如果x += 1
更清楚,为什么人们使用x++
和++x
?
【参考方案1】:
任何正常或疯狂的编译器都会为两者生成相同的机器代码。
【讨论】:
解释语言呢? 如果您使用的是解释型语言,则会遇到更大的性能问题。 我认为这回答了手头的问题。我认为可能是这种情况,但我只是想确定一下。 @tjameson:除此之外,像 PyPy 和 V8 这样的 JIT 编译解释器预计会处理这样的优化,它们真的是低调的水果(PyPy 家伙优化了 堆分配,几个月后这仍然让我惊叹)。 @delnan - 嗯,这很有趣。这是否意味着他们对开发商撒谎?我会假设new
将数据放在堆栈而不是堆上,但我想这并不重要,因为地址甚至无法访问。【参考方案2】:
假设您谈论将这些应用于基本类型并且没有自己的类可以产生巨大的差异,它们可以产生相同的输出,尤其是在启用优化时。令我惊讶的是,我经常在反编译的应用程序中发现 x += 1 在汇编程序级别(add vs inc)上用于 x++。
【讨论】:
嗯,这很有趣。 +1 汇编信息。 请注意,据我所知,它们是用 Visual Studio 编译的,我没有看到原始源代码,所以我无法确定源代码中是 += 还是 ++。 @Nobody- 只是好奇,但你认为 gcc 就是这种情况吗? 我真的不能这么说。我认为这取决于优化和架构设置等许多因素,但这可能由 gcc 开发人员或通过反编译一些准备好的测试用例来回答。 刚刚编写了一些小代码。 GCC 4.5.0 没有使用添加优化。对于 O1-3,它使用 lea。【参考方案3】:任何体面的编译器都应该能够识别出两者是相同的,因此最终它们之间应该没有性能差异。
如果你想说服自己,只需做一个基准测试..
【讨论】:
【参考方案4】:当您说“从长远来看可能会增加”时 - 不要那样想。
相反,从百分比的角度来考虑。当你发现程序计数器有 10% 或更多的时间在那个确切的代码中时,请担心它。 原因是,如果百分比很小,那么您可以通过改进它可以节省的最多也是很小的。
如果时间百分比低于 10%,您几乎可以肯定在代码的其他部分有更大的加速机会,几乎总是以您可以避免的函数调用的形式。
Here's an example.
【讨论】:
你说的是真的,迈克。但是,理解 x++ 和 x += 1 通常没有区别是有价值的。如果有区别,那么理解为什么要以一种或另一种方式编码是有意义的。考虑一下 Java 和 C# 中的字符串连接与字符串生成器。在某些情况下使用其中一种是有意义的,而在某些情况下使用另一种是有意义的。经验法则可以帮助您获得更好的代码和性能,但详细分析总能给出最终答案。 @aaaa:你当然是对的。在所有重要的情况下,重要的原因是它花费了大量的时间——正如你所说的“有道理”。你和我都知道这只是常识,但我仍然很惊讶有多少人还没有学会这一点。 是的,是的,但是如果我有一个模块可以将 RGB 批量转换为 BGR(有些图像向后使用它,不要问我为什么)。这将花费大部分时间在循环中进行一些位移。 @tjameson:这就是我所做的,它总是有效的。拿几个stackshots。每个人都告诉我当时它在做什么(更重要的是,正是为什么)。如果该代码中有两个或更多,则它具有足够高的百分比值得优化。它将直接指向花费时间的说明。这就是我知道我应该优化它的方式。再简单不过了。请注意,我不会这样做直到它告诉我我应该这样做。这是关键,因为问题可能出在其他地方。【参考方案5】:假设您是一个懒惰的编译器实现者,不会费心在机器代码生成模块中编写 OPTIMIZATION 例程。
x = x + 1;
将被翻译成这个代码:
mov $[x],$ACC
iadd $1,$ACC
mov $ACC,$[x]
x++ 会被翻译成:
incr $[x] ;increment by 1
如果 ONE 指令在 1 个机器周期内执行,则 x = x + 1 将花费 3 个机器周期,而 x++ 将花费 1 个机器周期。 (此处使用的假设机器)。
但幸运的是,大多数编译器实现者并不懒惰,并且会在 machine-code-gen 模块中编写优化。所以 x = x+1 和 x++ 应该花费相同的时间来执行。 :-P
【讨论】:
事实上,大多数编译器编写者都非常懒惰,以至于他们从不以中间形式实现增量指令。相反,他们有一个加法指令,并将这种优化留给后端。以上是关于递增:x++ 与 x += 1的主要内容,如果未能解决你的问题,请参考以下文章