I originally had a post here about the timing issue what was in favor of postfix increment, but it turned out to be completely invalid. Why? Because I wasn't assigning the values from the increments to anything, and my compiler turned out to be not stupid.
I ran the code a few more times, and ultimately, the times ended up being inconsistent for me. Sometimes postfix ran faster, sometimes prefix. So I decided to have a look at the assembly instead.
I compiled this C program to assembly with all optimizations disabled:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
|
#include <stdio.h>
#include <limits.h>
#include <time.h>
#include <stdint.h>
int main()
{
uint_least32_t i = 0;
int start, end;
uint_least32_t a, b;
start = clock()*1000/CLOCKS_PER_SEC;
while(i < UINT32_MAX)
a=++i;
end = clock()*1000/CLOCKS_PER_SEC;
printf("Prefix took: %d ms.",end-start);
i = 0;
start = clock()*1000/CLOCKS_PER_SEC;
while(i < UINT32_MAX)
b=i++;
end = clock()*1000/CLOCKS_PER_SEC;
printf("Postfix took: %d ms.",end-start);
return 0;
}
|
Why C? To reduce the amount of digging around I'd have to do for the loop implementations. EDIT: I went back and did this in C++, and the assembly for the loop bodies turned out to be the same.
##Prefix
movl -8(%rbp), %eax
addl $1, %eax
movl %eax, -8(%rbp)
movl %eax, -20(%rbp) |
##Postfix
movl -8(%rbp), %eax
movl %eax, %ecx
addl $1, %ecx
movl %ecx, -8(%rbp)
movl %eax, -24(%rbp)
|
As you can see, postfix increment calls for one extra mov operation and one extra registry. This is generally negligible. For comparison, here's the assembly for both loop bodies when the value is discarded:
##Both
movl -8(%rbp), %eax
addl $1, %eax
movl %eax, -8(%rbp) |
For incrementing basic variables, with modern compilers, there probably isn't much of a difference (if any).
When getting to complex types (i.e. classes) or when needing to store the value of the increment operation, that's a (very) different story.
I'll still use prefix ++ as a matter of habit, and you probably should too.
-Albatross