在Java和C ++中增加计数器的最佳方法是什么?

时间:2014-03-08 07:02:46

标签: java c++ performance calculator increment

这是在java中增加计数器(整数)的最佳方法。我对手术费用感兴趣。

int j = 0;
j = j + 1;

int i = 0;
i++;

它对于小程序几乎相同,但它对于大型计算,数千次迭代而言是不同的。

7 个答案:

答案 0 :(得分:3)

根据发布的其他答案,我觉得你应该看到所有三种技术的实例。以下是高度情境化的,但是非正式演示可以发生的事情:

守则

#include <stdio.h>>

int i=1;

int main()
{
    printf("i=%d\n", i);

    printf("i++ : %d\n", i++);

    printf("++i : %d\n", ++i);

    i = i + 1;
    printf("i=i+1 : %d\n", i);

    return 0;
}

工具

使用clang 3.3优化设置为-O2

大会清单

清理并注明消费:

; Basic printf()
movl    _i(%rip), %esi
leaq    L_.str(%rip), %rdi
xorb    %al, %al
callq   _printf

; post-increment (i++)
movl    _i(%rip), %esi
leal    1(%rsi), %eax
movl    %eax, _i(%rip)
leaq    L_.str1(%rip), %rdi
xorb    %al, %al
callq   _printf
leaq    L_.str2(%rip), %rdi

; pre-increment (++i)
movl    _i(%rip), %esi
incl    %esi
movl    %esi, _i(%rip)
xorb    %al, %al
callq   _printf
leaq    L_.str3(%rip), %rdi

; traditional (i = i + 1)
movl    _i(%rip), %esi
incl    %esi
movl    %esi, _i(%rip)
xorb    %al, %al
callq   _printf

差异

i vs i++的情况下,在增加之前存储包含++i的先前值的临时值。这只是 因为所谓的temp用作printf()函数调用的参数。另请注意,在预增量和传统机制中,生成的优化程序集相同movl, incl, movl)。

如果后增量操作评估,它会有所不同吗?

int main()
{
    i++;
    printf("i=%d\n", i);

    ++i;
    printf("i=%d\n", i);

    i = i + 1;
    printf("i=%d\n", i);

    return 0;
}

由此产生的组装是:

; post-increment
movl    _i(%rip), %esi
incl    %esi
movl    %esi, _i(%rip)
leaq    L_.str(%rip), %rbx
movq    %rbx, %rdi
xorb    %al, %al
callq   _printf

; pre-increment
movl    _i(%rip), %esi
incl    %esi
movl    %esi, _i(%rip)
movq    %rbx, %rdi
xorb    %al, %al
callq   _printf

 ; traditional
movl    _i(%rip), %esi
incl    %esi
movl    %esi, _i(%rip)
movq    %rbx, %rdi
xorb    %al, %al
callq   _printf

请注意,您看到的rbx魔法是无关的,只是缓存printf()的共享格式字符串的方法。在所有三种情况下,使用相同的代码(movl,incl,movl)。

<强>结论

对于独立语句,clang 3.3会将所有三个优化为相同的结果代码。如果引入评估依赖性,则后增量和预增量可以(并且可能会)发出不同的代码。如果您的增量是一个独立的声明,那么您选择的没有任何区别。

答案 1 :(得分:2)

使用前缀运算符比使用postfix更快。即++ii++快。

对于++i,值会增加并返回新值。

对于i++,值会增加,但会返回旧值。性能差异来自于需要首先存储较旧的值。

答案 2 :(得分:1)

不确定第一种方法,因为我从未以这种方式递增计数器(我相信其他人会进来)但是对于第二种方法,最好使用++ i而不是i ++。原因已经回答了那个in this question,但简而言之,i ++制作了i的副本,而++我直接在变量本身上工作。

答案 3 :(得分:1)

当你谈到增量或减量时,首先想到的是用于递增或递减的运算符,即++, -

在你的第一个案例当然会为你做增量工作,但它的增量技术间接方法,编译器需要做两个工作,1)增加2)分配。

在第二个编译器中,编译器知道它是递增运算符,因此它将递增该变量。

答案 4 :(得分:1)

++i比其他方法更快。

所以你的代码将是:

int i = 0;
++i;

答案 5 :(得分:1)

以下是一些Java源代码:

    int i = 0;

    i = i + 1;

    i += 1;

    ++i;

    i++;

这是相应的Java字节代码,由javap -c

获得
 0: iconst_0      
 1: istore_1      

 2: iload_1       
 3: iconst_1      
 4: iadd          
 5: istore_1      

 6: iinc          1, 1

 9: iinc          1, 1

12: iinc          1, 1

如您所见,最后三个语法形式编译为相同的JVM指令iinc。第一个产生更多的字节代码,但如果JIT编译器没有优化这种差异,我会感到惊讶。

答案 6 :(得分:0)

@Modred:对于你引用的两种方法的使用,在影响的情况下结果是不一样的。 对于以下代码,结果不一样:

int i = 0, j = 0,k = 0;
cout << "i = " << i <<  " ,j = " << j << " ,k = " << k << '\n';
j = i++;
cout << "i = " << i <<  " ,j = " << j << " ,k = " << k << '\n';
k = ++i;
cout << "i = " << i <<  " ,j = " << j << " ,k = " << k << '\n';

<强>输出

i = 0 ,j = 0 ,k = 0
i = 1 ,j = 0 ,k = 0
i = 2 ,j = 0 ,k = 2