如果不使用结果值,i++和++i之间是否有性能差异?


当前回答

摘自Andrew Koenig的《效率与意图》:

首先,++i是否比i++更有效还不明显,至少在涉及整型变量时是这样。

和:

所以人们应该问的问题不是这两种操作中哪一种更快,而是这两种操作中哪一种更准确地表达了你想要完成的事情。我认为,如果你不使用表达式的值,永远没有理由使用i++而不是++ I,因为永远没有理由复制一个变量的值,增加变量,然后扔掉拷贝。

因此,如果没有使用结果值,则使用++ I。但不是因为它更有效,而是因为它正确地表达了我的意图。

其他回答

参考Scott Meyers的《更有效的c++第六条:区分增减操作的前缀和后缀形式》。

对于对象,尤其是对于迭代器,前缀版本总是优于后缀版本。

原因是,如果你看一下操作符的调用模式。

// Prefix
Integer& Integer::operator++()
{
    *this += 1;
    return *this;
}

// Postfix
const Integer Integer::operator++(int)
{
    Integer oldValue = *this;
    ++(*this);
    return oldValue;
}

看看这个例子,很容易看出前缀操作符总是比后缀操作符更有效率。因为需要在临时对象中使用后缀。

这就是为什么当你看到使用迭代器的例子时,他们总是使用前缀版本。

但正如你所指出的,对于int型,实际上没有什么区别,因为编译器优化可以发生。

更好的答案是++i有时会更快,但绝不会变慢。

每个人似乎都认为i是一个常规的内置类型,比如int。在这种情况下,将没有可测量的差异。

然而,如果i是复型,那么你很可能会发现一个可测量的差异。对于i++,您必须在递增类之前复制它。根据复制中涉及的内容,它确实可能会变慢,因为使用++i可以只返回最终值。

Foo Foo::operator++()
{
  Foo oldFoo = *this; // copy existing value - could be slow
  // yadda yadda, do increment
  return oldFoo;
}

另一个区别是,使用++i,您可以选择返回一个引用而不是一个值。同样,根据复制对象所涉及的内容,这可能会更慢。

在现实世界中,迭代器的使用就是可能发生这种情况的一个例子。复制迭代器不太可能成为应用程序中的瓶颈,但养成使用++i而不是i++的习惯仍然是一个很好的实践,因为i++的结果不会受到影响。

我已经阅读了这里的大部分答案和许多评论,我没有看到任何一个我能想到的实例,在哪里i++比++ I更有效(也许令人惊讶的是- I比I更有效)。这是针对DEC PDP-11的C编译器!

PDP-11的汇编指令用于寄存器的前减和后增,但没有相反的指令。这些指令允许任何“通用”寄存器用作堆栈指针。所以如果你使用像*(i++)这样的东西,它可以被编译成一个汇编指令,而*(++i)不能。

这显然是一个非常深奥的例子,但它确实提供了后增量更有效的例外(或者我应该说曾经,因为现在对PDP-11 C代码的需求并不多)。

在C语言中,如果结果未被使用,编译器通常可以将它们优化为相同。

然而,在c++中,如果使用提供自己的++操作符的其他类型,前缀版本可能比后缀版本更快。因此,如果不需要后缀语义,最好使用前缀操作符。

@Mark 即使编译器允许优化(基于堆栈的)变量的临时副本,并且gcc(在最近的版本中)正在这样做, 这并不意味着所有编译器都会这样做。

我刚刚用我们在当前项目中使用的编译器测试了它,4个中有3个没有优化它。

永远不要假设编译器是正确的,特别是如果可能更快,但永远不会更慢的代码很容易阅读。

如果你的代码中没有一个操作符的愚蠢实现:

我喜欢++i胜过i++。