views:

609

answers:

6

I'm well aware that in C++

int someValue = i++;
array[i++] = otherValue;

has different effect compared to

int someValue = ++i;
array[++i] = otherValue;

but every once in a while I see statements with prefix increment in for-loops or just by their own:

for( int i = 0; i < count; ++i ) {
     //do stuff
}

or

for( int i = 0; i < count; ) {
    //do some stuff;
    if( condition ) {
        ++i;
    } else {
        i += 4;
    }
}

In the latter two cases the ++i looks like an attempt to produce smarty-looking code. Am I overseeing something? Is there a reason to use ++i instead of i++ in the latter two cases?

+4  A: 

There is one reason, and it has to do with overloaded operators. In an overloaded postincrement function, the function must remember the previous value of the object, increment it, and then return the previous value. In a preincrement function, the function can simply increment the object and then return a reference to itself (its new value).

In the case of an integer, the above probably won't apply because the compiler knows the context in which the increment is being done, and will generate appropriate increment code in either case.

Greg Hewgill
does this mean that for the example given where i is an int, it's bogus since it won't amount to any additional speedup?
Toad
I would add that this only applies to objects. I don't think you can overload ++ for an int, can you? It's possible that it might be faster for brain-dead compilers, but any decent compiler should be able to optimize i++ and ++i to the same sequence (for ints, at least).
paxdiablo
Right, I just amended my answer to include that.
Greg Hewgill
@Pax: In C++, when you write `int i;`, then `i` is an "object", too. (C++ isn't Java.)
sbi
@reinier - the argument usually used there is that it's silly to use post-increment for integer and pointer types "because there's no speedup", but then switch to pre-increment for non-trivial iterators. Saying that using ++i is "bogus" where there's no performance difference presupposes that i++ is preferable for other reasons, which is merely an assertion that you don't trust that your colleagues know C well enough to comfortably read whichever. If people were this cautious about readability the rest of the time, I'd have handled a lot less crappy code in my life...
Steve Jessop
+2  A: 

Yes, for performance reasons. In case of post increment a copy of the variable i needs to be made before incrementing so that the old value can be returned (eventhough you are not using the return value). In case of pre-increment this copy is not required.

Naveen
Why downvote? Is something wrong in the description?
Naveen
+1  A: 

There is little reason to favour pre-increment over post-increment when you are talking about natural types like integers. The compiler is typically able to generate the same code in both cases anyway, assuming you don't use the return value. This is not true for more complex types, such as iterators.

1800 INFORMATION
True, but it is still better to train yourself to always use the pre-increment form in such cases, rather than think about the variable's type. The code is more consistent, and is robust if the type changes.
tragomaskhalos
+34  A: 

Look at possible implementations of the two operators in own code:

// Pre-increment
T*& operator ++() {
    // Perform increment operation.
    return *this;
}

// Post-increment
T operator ++(int) {
    T copy = *this;
    ++*this;
    return copy;
}

The postfix operator invokes the prefix operator to perform its own operation: by design and in principle the prefix version will always be faster than the postfix version, although the compiler can optimize this in many cases (and especially for builtin types).

The preference for the prefix operator is therefore natural; it’s the other that needs explanation: why are so many people intrigued by the use of the prefix operator in situations where it doesn’t matter – yet nobody is ever astonished by the use of the postfix operator.

Konrad Rudolph
Because C++ is standard, but who has heard of ++C?
MaxVT
If you're going to wildly fantasise that the name of the C++ language actually has any bearing on how code should be written, then that name should be C+1, since mentioning it does not in point of fact modify the C language every time...
Steve Jessop
+7  A: 

As you noted - it does not matter to the result.

There is a performance consideration for non-primitive types.

Also semantically using pre-increment is usually clearer in showing the intention of a test when the return value is used, so its better to use it habitually than post-increment to avoid accidentally testing the old value.

Timothy Pratley
Not true; Sometimes it does make a difference. For example; x = (++x % 10), in which x cycles from 0 through 9, won't work if you use post increment. There are examples where the reverse is true. It's important to know the difference and "say what you mean" rather than hope the optimiser guesses correctly for you.
Chris Huang-Leaver
Hi Chris - your comment doesn't seem relevant. The question is about cases where using either ++x or x++ will give precisely the same result. Clearly the difference is when the result is used or not, and if you are using the result you need to choose the correct one. Perhaps you disagree with my suggestion that it is less clear using post-fix, I guess that is subjective... but I find at first glance it is easy to confuse the meaning of a[x++] = 1 which could be alternatively written as a[x] = 1; ++x; whereas b[++y] = 2 is rarely misunderstood.
Timothy Pratley
+12  A: 

If we ignore force of habit, '++i' is a simpler operation conceptually: It simply adds one to the value of i, and then uses it.

i++ on the other hand, is "take the original value of i, store it as a temporary, add one to i, and then return the temporary". It requires us to keep the old value around even after i has been updated.

And as Konrad Rudolph showed, there can be performance costs to using i++ with user-defined types.

So the question is, why not always just default to ++i?

If you have no reason to use `i++´, why do it? Why would you default to the operation which is more complicated to reason about, and may be slower to execute?

jalf
Great description of the other aspect - complicated to reason about. I think its an important aspect.
Timothy Pratley