Java中,++x比x++更高效吗?

17
在一节编程课上,教授正在向我们介绍有关 `x++` 和 `++x` 的知识,其中 x 是一个整数。

他说,在我们可以使用 `x++` 或 `++x` 的情况下,`++x` 更有效率(尽管理论上差异不大)。

但我忘记了原因。有人知道吗?这是在讲 Java 语言时提到的。


6
为什么您的教授会在如此微不足道的细节上花费精力呢? - Johan Sjöberg
1
这位教授是谁?我很好奇。 :P - Mysticial
1
以下是关于C++的相关讨论:C++中前置递增比后置递增更快 - 是真的吗?如果是,为什么? - Roddy of the Frozen Peas
6
请向教授询问Java中的基准以验证这个声明 :) 我还将标题从“断言”改为“问题”。 - user166390
无论如何,所有询问“为什么”的性能问题都应该附带一个基准测试和一个SSCCE - Mysticial
显示剩余3条评论
3个回答

27

在Java中,使用递增/递减运算符的效率并不更高。在可以重载递增/递减运算符的语言中,它可能更高效,但否则性能完全相同。

x++++x之间的区别在于,x++返回递增前的x值,而++x返回递增后的x值。在代码生成方面,两者至少在可互换使用时生成相同数量的指令(如果不能互换使用,则不应该担心哪个更快,而应选择所需的一个)。唯一的区别是递增指令的位置。

在C++中,类可以重载前缀(++x)和后缀(x++)运算符。当处理重载它们的类型时,使用前缀运算符几乎普遍更快,因为后缀运算符的语义将返回对象在递增之前的副本,即使您不需要它,而前缀运算符可以简单地返回对修改后的对象的引用(上帝知道C++开发人员更喜欢返回引用而不是副本)。这可能是考虑使用++x优于x++的原因:如果您习惯于使用++x,当/如果切换到C++时,您可以节省一些轻微的性能问题。但在Java环境中,两者完全等效。

与上面评论中的pst一样,我从不使用x++++x的返回值,如果您也从不使用,请坚持您更喜欢的那个。


1
"C++开发者更喜欢返回引用而不是副本" ...因为副本很昂贵?当然,编译器可以在许多实际情况下消除副本,但为什么要依赖这种假设,当你可以避免在第一时间创建一个呢? - Stefano Sanfilippo

16

出于好奇,您可以检查生成的字节码。

这个程序:

public static void main(String args[]) {
    int i = 1; //bytecode 0, 1
    i++; //bytecode 2
    ++i; //bytecode 5
    int a = ++i; //bytecode 8, 11, 12
    int b = i++; //bytecode 13, 14, 17
}

生成以下字节码:

  public static void main(java.lang.String[]);
    Code:
       0: iconst_1
       1: istore_1
       2: iinc          1, 1
       5: iinc          1, 1
       8: iinc          1, 1
      11: iload_1
      12: istore_2
      13: iload_1
      14: iinc          1, 1
      17: istore_3
      18: return

因此,您可以看到从字节码的角度来看,前缀和后缀运算符是严格相同的(除了操作顺序)。

如果JIT编译器编译代码的那部分,则情况未知。例如,上面的代码本身可能会被编译为无操作,因为它没有副作用。


4
事实是在PDP-11和可能的VAX上,在C语言中*x++*++x更快,因为它编译成单个指令(自增寄存器延迟)。同样,*--x*x--更快。如果没有解除引用,使用任一形式只会在一个情况下比另一个快,如果编译器仍然生成该指令,则这将是浪费的,因为解除引用仍将发生。

那些日子早已过去了。


我非常确定这是错误的,在PDP-11上,*x++*x--都比另一个更有效率。现在,在一个“现代”的架构中,并且不涉及解引用,x++可能需要一个++x不需要的临时变量,这可能就是告诉OP的人所指的。 - Random832

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接