Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I've read that I should avoid the postfix increment operator because of performance reasons (in certain cases).

But doesn't this affect code readability? In my opinion:

for(int i = 0; i < 42; i++);
    /* i will never equal 42! */

Looks better than:

for(int i = 0; i < 42; ++i);
    /* i will never equal 42! */

But this is probably just out of habit. Admittedly, I haven't seen many use ++i.

Is the performance that bad to sacrifice readability, in this case? Or am I just blind, and ++i is more readable than i++?

share|improve this question
    
If you're not convinced by the reasons presented in the research you've already done, I'm not sure I understand what your question is. Are you looking for affirmation of your opinion about what looks better? –  user8 Mar 19 '11 at 7:06
1  
I used i++ before I knew it could affect performance over ++i, so I switched. At first the latter did look a little strange, but after a little while I got used to it and now it feels as natural as i++. –  gablin Mar 19 '11 at 9:41
9  
++i and i++ do different things in certain contexts, do not assume they are the same. –  Orbling Mar 19 '11 at 11:32
1  
Is this about C or C++? They are two very different languages! :-) In C++ the idiomatic for-loop is for (type i = 0; i != 42; ++i). Not only can operator++ be overloaded, but so can operator!= and operator<. Prefix increment is not more expensive than postfix, not-equal is not more expensive than less-than. Which ones should we use? –  Bo Persson Mar 19 '11 at 20:39
2  
Shouldn't it be called ++C? –  Alison Mar 21 '11 at 11:05
show 7 more comments

11 Answers 11

up vote 28 down vote accepted

The facts:

  1. i++ and ++i are equally easy to read. You don't like one because you're not used to it, but there's essentially nothing you can misinterpret it as, so it's no more work to read or write.

  2. In at least some cases, the postfix operator will be less efficient.

  3. However, in 99.99% cases, it won't matter because (a) it'll be acting on a simple or primitive type anyway and it's only a problem if it's copying a big object (b) it won't be in a performance critical part of code (c) you don't know if the compiler will optimise it or not, it may do.

  4. Thus, I suggest using prefix unless you specifically need postfix is a good habit to get into, just because (a) it's a good habit to be precise with other things and (b) once in a blue moon you'll intend to use postfix and get it the wrong way round: if you always write what you mean, that's less likely. There is always a trade-off between performance and optimisation.

You should use you common sense and not micro-optimise until you need to, but neither be flagrantly inefficient for the sake of it. Typically this means: first, rule out any code construction which is unacceptably inefficient even in non-time-critical code (normally something representing a fundamental conceptual error, like passing 500MB objects by value for no reason); and second, of every other way of writing the code, choose the clearest.

However, here, I believe the answer is simple: I believe writing prefix unless you specifically need postfix is (a) very marginally clearer and (b) very marginally more likely to be more efficient, so you should always write that by default, but not worry about it if you forget.

Six months ago, I thought the same as you, that i++ was more natural, but it's purely what you're used to.

EDIT 1: Scott Meyers, in "More Effective C++" who I generally trust on this thing, says you should in general avoid using the postfix operator on user-defined types (because the only sane implementation of the postfix increment function is to make a copy of the object, call the prefix increment function to perform the increment, and return the copy, but copy operations can be expensive).

So, we don't know whether there are any general rules about (a) whether that is true today, (b) whether it also applies (less so) to intrinsic types (c) whether you should be using "++" on anything more than a lightweight iterator class ever. But for all the reasons I described above, it doesn't matter, do what I said before.

EDIT 2: This refers to general practice. If you think it DOES matter in some specific instance, then you should profile it and see. Profiling is easy and cheap and works. Deducing from first principles what needs to be optimized is hard and expensive and doesn't work.

share|improve this answer
    
Your posting is right on the money. In expressions where the infix + operator and post-increment ++ have been overloaded such as aClassInst = someOtherClassInst + yetAnotherClassInst++, the parser will generate code to perform the additive operation before generating the code to perform the post-increment operation, alleviating the need to create a temporary copy. The performance killer here is not post-increment. It is the use of an overloaded infix operator. Infix operators produce new instances. –  bit-twiddler Mar 22 '11 at 17:24
add comment

Always code for the programmer first and the computer second.

If there is a performance difference, after the compiler has cast its expert eye over your code, AND you can measure it AND it matters - then you can change it.

share|improve this answer
4  
SUPERB statement!!! –  Dave Mar 19 '11 at 20:27
    
@Martin: which is exactly why I'd use prefix increment. Postfix semantics imply keeping the old value around, and if there's no need for it, then it's inaccurate to use it. –  Matthieu M. Mar 20 '11 at 19:36
1  
For a loop index that would be clearer - but if you were iterating over an array by incrementing a pointer and use prefix meant starting at an illegal address one before the start that would be bad irrespective of an performance boost –  Martin Beckett Mar 20 '11 at 22:07
    
"it's" -> "its" –  Jason S Mar 21 '11 at 12:49
1  
@Matthew: It is simply not true that post-increment implies keeping a copy of the old value around. One cannot be sure how a compiler handles intermediate values until one views its output. If you take the time to view my annotated GCC generated assembly language listing, you will see that GCC generates the same machine code for both loops. This nonsense about favoring pre-increment over post-increment because it is more efficient is little more than conjecture. –  bit-twiddler Mar 21 '11 at 13:37
show 3 more comments

GCC produces the same machine code for both loops.

C Code

int main(int argc, char** argv)
{
    for (int i = 0; i < 42; i++)
            printf("i = %d\n",i);

    for (int i = 0; i < 42; ++i)
        printf("i = %d\n",i);

    return 0;
}

Assembly Code (with my comments)

    cstring
LC0:
    .ascii "i = %d\12\0"
    .text
.globl _main
_main:
    pushl   %ebp
    movl    %esp, %ebp
    pushl   %ebx
    subl    $36, %esp
    call    L9
"L00000000001$pb":
L9:
    popl    %ebx
    movl    $0, -16(%ebp)  // -16(%ebp) is "i" for the first loop 
    jmp L2
L3:
    movl    -16(%ebp), %eax   // move i for the first loop to the eax register 
    movl    %eax, 4(%esp)     // push i onto the stack
    leal    LC0-"L00000000001$pb"(%ebx), %eax // load the effective address of the format string into the eax register
    movl    %eax, (%esp)      // push the address of the format string onto the stack
    call    L_printf$stub    // call printf
    leal    -16(%ebp), %eax  // make the eax register point to i
    incl    (%eax)           // increment i
L2:
    cmpl    $41, -16(%ebp)  // compare i to the number 41
    jle L3              // jump to L3 if less than or equal to 41
    movl    $0, -12(%ebp)   // -12(%ebp) is "i" for the second loop  
    jmp L5
L6:
    movl    -12(%ebp), %eax   // move i for the second loop to the eax register 
    movl    %eax, 4(%esp)     // push i onto the stack
    leal    LC0-"L00000000001$pb"(%ebx), %eax // load the effective address of the format string into the eax register
    movl    %eax, (%esp)      // push the address of the format string onto the stack
    call    L_printf$stub     // call printf
    leal    -12(%ebp), %eax  // make eax point to i
    incl    (%eax)           // increment i
L5:
    cmpl    $41, -12(%ebp)   // compare i to 41 
    jle L6               // jump to L6 if less than or equal to 41
    movl    $0, %eax
    addl    $36, %esp
    popl    %ebx
    leave
    ret
    .section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5
L_printf$stub:
    .indirect_symbol _printf
    hlt ; hlt ; hlt ; hlt ; hlt
    .subsections_via_symbols
share|improve this answer
1  
+1, for actually investigate the matter –  user1041 Mar 30 '12 at 8:39
add comment

In C++, you could make a substantial performance difference if there are operator overloads involved, especially if you're writing templated code and don't know what iterators might be passed in. The logic behind any iterator X may be both substantial and significant- that is, slow, and unoptimizable by the compiler.

But this is not the case in C, where you know it will only be a trivial type, and the performance difference is trivial and the compiler can easily optimize away.

So a tip: You program in C, or in C++, and questions relate to one or the other, not both.

share|improve this answer
add comment

Don't worry about performance, say 97% of the time. Premature Optimization is the Root of all Evil.

-- Donald Knuth

Now that this is out of our way, let's make our choice sanely:

  • ++i: prefix increment, increment the current value and yields the result
  • i++: postfix increment, copy the value, increment the current value, yields the copy

Unless a copy of the old value is required, using postfix increment is a round-about way of getting things done.

Inaccuracy comes from laziness, always use the construct that expresses your intent in the most direct way, there's less chance than the future maintainer might misunderstand your original intent.

Even though it's (really) minor here, there are times when I've been really puzzled by reading code: I was truly wondering whether the intent and the actual express coincided, and of course, after a few months, they (or I) didn't remember either...

So, it doesn't matter whether it looks right to you, or not. Embrace KISS. In a few months you'll have shun your old practices.

share|improve this answer
add comment

If you want to know if something's slow, test it. Take a BigInteger or equivalent, stick it in a similar for loop using both idioms, make sure the inside of the loop doesn't get optimized away, and time them both.

Having read the article, I don't find it very convincing, for three reasons. One, the compiler should be able to optimize around the creation of an object that is never used. Two, the i++ concept is idiomatic for numeric for loops, so the cases I can see actually being affected are limited to . Three, they provide a purely theoretical argument, with no numbers to back it up.

Based on reason #1 especially, my guess is that when you actually do the timing, they will be right next to each other.

share|improve this answer
add comment

The performance of either operation is highly dependent on the underlying architecture. One has to increment a value that is stored in memory, which means that the von Neumann bottleneck is the limiting factor in both cases.

In the case of ++i, we have to

Fetch i from memory 
Increment i
Store i back to memory
Use i

In the case of i++, we have to

Fetch i from memory
Use i
Increment i
Store i back to memory

The ++ and -- operators trace their origin to the PDP-11 instruction set. The PDP-11 could perform automatic post-increment on a register. It could also perform automatic pre-decrement on an effective address contained in a register. In either case, the compiler could only take advantage of these machine-level operations if the variable in question was a "register" variable.

share|improve this answer
add comment

I think semantically, ++i makes more sense than i++, so I'd stick to the first one, except it's common to not do so (like in Java, where you should use i++ because it's widely used).

share|improve this answer
add comment

First of all it doesn't affect readability IMO. Its not what your used to seeing but it would only be a short while before you got accustomed to it.

Second unless you use a ton of postfix operators in your code you're likely not to see much of a difference. The main argument for not using them when possible is that a copy of the original var's value has to be kept until the end of the arguments where the original var could still be used. That's either 32bits or 64bits depending on the architecture. That equates to 4 or 8 bytes or 0.00390625 or 0.0078125 MB. Chances are very high that unless you're using a ton of them which need to be saved for a very long period of time that with today's computer resources and speed you wouldn't even notice a difference making a switch from postfix to prefix.

EDIT: Forget this remaining portion as my conclusion was proven false (except for the part of ++i and i++ not always doing the same thing... that's still true).

Also it was pointed out earlier that they don't do the same thing in a cases. Be careful about making the switch if you decide to. I've never tried it out (I've always used postfix) so I don't know for sure but I think changing from postfix to prefix will result in different results: (again I could be wrong... depends on the compiler/interpreter too)

for (int i=0; i < 10; i++) //the set of i values here will be {0,1,2,3,4,5,6,7,8,9}
for (int i=0; i < 10; ++i) //the set of i values here will be {1,2,3,4,5,6,7,8,9,10}
share|improve this answer
    
The increment operation occurs at the end of the for loop, so they would have the exact same output. It's not dependent on the compiler/interpreter. –  jsternberg Mar 19 '11 at 16:24
    
@jsternberg... Thanks I wasn't sure when the increment happened as I never really had a reason to ever go test it out. Its been too long since I did compilers in college! lol –  Kenneth Mar 19 '11 at 16:29
add comment

It's not about only performance.

Sometimes you want to avoid implementing copying at all, because it doesn't make sense. And since usage of prefix increment does not depend on this it's plainly simpler to stick to prefix form.

And using different increments for primitive types and complex types... that's really unreadable.

share|improve this answer
add comment

Unless you really need it, I'd stick to ++i. In most cases, this is what one intends. It's not very often you need i++, and you always have to think twice when reading such a construct. With ++i, it's easy: you add 1, use it, and then i is still the same.

So, I agree full-hearty with @martin beckett: make it easier for yourself, it's already hard enough.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.