如果不使用结果值,i++和++i之间是否有性能差异?
当前回答
如果你担心微观优化,这里有一个额外的观察。递减循环“可能”比递增循环更有效(取决于指令集架构,例如ARM),给定:
for (i = 0; i < 100; i++)
在每个循环中,你将有一个指令:
i加1。 比较i是否小于100。 如果i小于100,则为条件分支。
而递减循环:
for (i = 100; i != 0; i--)
循环将有一个指令用于以下每一个:
递减i,设置CPU寄存器状态标志。 一个依赖于CPU寄存器状态(Z==0)的条件分支。
当然,这只适用于递减到零!
记得ARM系统开发人员指南。
其他回答
参考Scott Meyers的《更有效的c++第六条:区分增减操作的前缀和后缀形式》。
对于对象,尤其是对于迭代器,前缀版本总是优于后缀版本。
原因是,如果你看一下操作符的调用模式。
// Prefix
Integer& Integer::operator++()
{
*this += 1;
return *this;
}
// Postfix
const Integer Integer::operator++(int)
{
Integer oldValue = *this;
++(*this);
return oldValue;
}
看看这个例子,很容易看出前缀操作符总是比后缀操作符更有效率。因为需要在临时对象中使用后缀。
这就是为什么当你看到使用迭代器的例子时,他们总是使用前缀版本。
但正如你所指出的,对于int型,实际上没有什么区别,因为编译器优化可以发生。
在C语言中,如果结果未被使用,编译器通常可以将它们优化为相同。
然而,在c++中,如果使用提供自己的++操作符的其他类型,前缀版本可能比后缀版本更快。因此,如果不需要后缀语义,最好使用前缀操作符。
我可以想到一种情况,后缀比前缀增量慢:
想象一个寄存器a的处理器被用作累加器,它是许多指令中使用的唯一寄存器(一些小型微控制器实际上是这样的)。
现在想象一下下面的程序和它们转换成一个假设的程序集:
前缀增量:
a = ++b + c;
; increment b
LD A, [&b]
INC A
ST A, [&b]
; add with c
ADD A, [&c]
; store in a
ST A, [&a]
后缀增加:
a = b++ + c;
; load b
LD A, [&b]
; add with c
ADD A, [&c]
; store in a
ST A, [&a]
; increment b
LD A, [&b]
INC A
ST A, [&b]
注意b的值是如何被强制重新加载的。使用前缀增量,编译器可以只增加值并继续使用它,可能避免重新加载它,因为所需的值在增量之后已经在寄存器中。然而,使用后缀增量,编译器必须处理两个值,一个是旧值,一个是增加的值,正如我上面所示,这会导致更多的内存访问。
当然,如果增量的值没有被使用,比如单个i++;语句,编译器可以(并且确实)简单地生成一个增量指令,而不管后缀或前缀的使用。
As a side note, I'd like to mention that an expression in which there is a b++ cannot simply be converted to one with ++b without any additional effort (for example by adding a - 1). So comparing the two if they are part of some expression is not really valid. Often, where you use b++ inside an expression you cannot use ++b, so even if ++b were potentially more efficient, it would simply be wrong. Exception is of course if the expression is begging for it (for example a = b++ + 1; which can be changed to a = ++b;).
摘自Andrew Koenig的《效率与意图》:
首先,++i是否比i++更有效还不明显,至少在涉及整型变量时是这样。
和:
所以人们应该问的问题不是这两种操作中哪一种更快,而是这两种操作中哪一种更准确地表达了你想要完成的事情。我认为,如果你不使用表达式的值,永远没有理由使用i++而不是++ I,因为永远没有理由复制一个变量的值,增加变量,然后扔掉拷贝。
因此,如果没有使用结果值,则使用++ I。但不是因为它更有效,而是因为它正确地表达了我的意图。
我已经阅读了这里的大部分答案和许多评论,我没有看到任何一个我能想到的实例,在哪里i++比++ I更有效(也许令人惊讶的是- I比I更有效)。这是针对DEC PDP-11的C编译器!
PDP-11的汇编指令用于寄存器的前减和后增,但没有相反的指令。这些指令允许任何“通用”寄存器用作堆栈指针。所以如果你使用像*(i++)这样的东西,它可以被编译成一个汇编指令,而*(++i)不能。
这显然是一个非常深奥的例子,但它确实提供了后增量更有效的例外(或者我应该说曾经,因为现在对PDP-11 C代码的需求并不多)。
推荐文章
- 如何有效地从数组列表或字符串数组中删除所有空元素?
- 在SQL Server上使用varchar(MAX) vs TEXT
- c++中size_t和int的区别是什么?
- .toArray(new MyClass[0]) or .toArray(new MyClass[myList.size()])?
- 在C和c++中静态变量存储在哪里?
- 是什么导致JNI调用变慢?
- 检查属性是否有属性
- errno线程安全吗?
- 如何快速清除JavaScript对象?
- 如何在C程序中获取当前目录?
- 互斥实例/教程?
- 如何添加一个'或'条件在#ifdef
- extern关键字对C函数的影响
- Node.js vs .Net性能
- 如果使用if-return-return或if-else-return?