++i or i++ in for loops ?? [duplicate]
Asked Answered
P

9

65

Possible Duplicate:
Is there a performance difference between i++ and ++i in C++?

Is there a reason some programmers write ++i in a normal for loop instead of writing i++?

Peristyle answered 23/11, 2010 at 22:37 Comment(0)
C
93

For integers, there is no difference between pre- and post-increment.

If i is an object of a non-trivial class, then ++i is generally preferred, because the object is modified and then evaluated, whereas i++ modifies after evaluation, so requires a copy to be made.

Cyrenaic answered 23/11, 2010 at 22:40 Comment(8)
Although the same code is generated with integers, because of the second paragraph, it's probably a good idea to go with ++i for all types, so that you are in the habit of using it for all types.Aminta
@Token: I agree in principle. However, i++ is somewhat idiomatic in C code; if you regularly use both languages, it can get confusing...Cyrenaic
Pardon my ignorance here, but this sure sounds silly. Imagine that i is an instance of some class that overloads the increment operator. Are you saying that if I were to simply post-increment (not in a loop control statement, but rather just increment it) (i.e. i++;), that the compiler wouldn't be able to see that I'm not doing anything with the return value, and automatically re-write that to be ++i?Ascendancy
@Jim: the compiler has to call the relevant operator overload (operator++() or operator++(int) for preincrement and postincrement respectively). If they're actually equivalent, and if the call is inlined, and if the copies involved are all removed by the optimizer, then the emitted code may end up the same - try it. But the compiler certainly can't replace one with the other solely on the basis that the result is unused. I don't especially care, because I write ++i for clarity (as I perceive it). "increment i" -> "++i".Apiculate
@Jim Mischel: The compiler can see that the return value isn't being used, but it has no reason to expect that ++i and i++ have the same semantics modulo the copy. So it has to call the version that the programmer asked for.Slowpoke
egads, it's been so long, I forgot that post-increment and pre-increment are two entirely different operators in C++, which can be overloaded independently. Thanks.Ascendancy
The second reason is a good reason to always use the prefix ++. The reason being that code is always being modified, and what is an integer (pointer) today will become an iterator tomorrow. Thus you want to be able to change the type without having to go through all the code and change its usage.Seisin
@Oli: Heavens forbid that code being idiomatic in C would be a good reason to use it in C++ as well!Emmerie
S
140

++i is slightly more efficient due to its semantics:

++i;  // Fetch i, increment it, and return it
i++;  // Fetch i, copy it, increment i, return copy

For int-like indices, the efficiency gain is minimal (if any). For iterators and other heavier-weight objects, avoiding that copy can be a real win (particularly if the loop body doesn't contain much work).

As an example, consider the following loop using a theoretical BigInteger class providing arbitrary precision integers (and thus some sort of vector-like internals):

std::vector<BigInteger> vec;
for (BigInteger i = 0; i < 99999999L; i++) {
  vec.push_back(i);
}

That i++ operation includes copy construction (i.e. operator new, digit-by-digit copy) and destruction (operator delete) for a loop that won't do anything more than essentially make one more copy of the index object. Essentially you've doubled the work to be done (and increased memory fragmentation most likely) by simply using the postfix increment where prefix would have been sufficient.

Slowpoke answered 23/11, 2010 at 22:41 Comment(0)
C
93

For integers, there is no difference between pre- and post-increment.

If i is an object of a non-trivial class, then ++i is generally preferred, because the object is modified and then evaluated, whereas i++ modifies after evaluation, so requires a copy to be made.

Cyrenaic answered 23/11, 2010 at 22:40 Comment(8)
Although the same code is generated with integers, because of the second paragraph, it's probably a good idea to go with ++i for all types, so that you are in the habit of using it for all types.Aminta
@Token: I agree in principle. However, i++ is somewhat idiomatic in C code; if you regularly use both languages, it can get confusing...Cyrenaic
Pardon my ignorance here, but this sure sounds silly. Imagine that i is an instance of some class that overloads the increment operator. Are you saying that if I were to simply post-increment (not in a loop control statement, but rather just increment it) (i.e. i++;), that the compiler wouldn't be able to see that I'm not doing anything with the return value, and automatically re-write that to be ++i?Ascendancy
@Jim: the compiler has to call the relevant operator overload (operator++() or operator++(int) for preincrement and postincrement respectively). If they're actually equivalent, and if the call is inlined, and if the copies involved are all removed by the optimizer, then the emitted code may end up the same - try it. But the compiler certainly can't replace one with the other solely on the basis that the result is unused. I don't especially care, because I write ++i for clarity (as I perceive it). "increment i" -> "++i".Apiculate
@Jim Mischel: The compiler can see that the return value isn't being used, but it has no reason to expect that ++i and i++ have the same semantics modulo the copy. So it has to call the version that the programmer asked for.Slowpoke
egads, it's been so long, I forgot that post-increment and pre-increment are two entirely different operators in C++, which can be overloaded independently. Thanks.Ascendancy
The second reason is a good reason to always use the prefix ++. The reason being that code is always being modified, and what is an integer (pointer) today will become an iterator tomorrow. Thus you want to be able to change the type without having to go through all the code and change its usage.Seisin
@Oli: Heavens forbid that code being idiomatic in C would be a good reason to use it in C++ as well!Emmerie
R
10

++i is a pre-increment; i++ is post-increment.
The downside of post-increment is that it generates an extra value; it returns a copy of the old value while modifying i. Thus, you should avoid it when possible.

Rivers answered 23/11, 2010 at 22:40 Comment(0)
C
5

With integers, it's preference.

If the loop variable is a class/object, it can make a difference (only profiling can tell you if it's a significant difference), because the post-increment version requires that you create a copy of that object that gets discarded.

If creating that copy is an expensive operation, you're paying that expense once for every time you go through the loop, for no reason at all.

If you get into the habit of always using ++i in for loops, you don't need to stop and think about whether what you're doing in this particular situation makes sense. You just always are.

Cipher answered 23/11, 2010 at 22:44 Comment(0)
A
3

No compiler worth its weight in salt will run differently between

for(int i=0; i<10; i++)

and

for(int i=0;i<10;++i)

++i and i++ have the same cost. The only thing that differs is that the return value of ++i is i+1 whereas the return value of i++ is i.

So for those prefering ++i, there's probably no valid justification, just personal preference.

EDIT: This is wrong for classes, as said in about every other post. i++ will generate a copy if i is a class.

Apposition answered 23/11, 2010 at 22:39 Comment(4)
That's probably true for int-like indices, but not generally true for iterators and other objects that might act as indices.Slowpoke
doesn't i++ and ++i call the same operator?Apposition
No, ++i calls i.operator++() and i++ calls i.operator(int). See my answer for implementation details.Erythrite
100% agreed with what @FredOverflow said. Think of it this way, there is no reason to write i++, but there might be a reason to write ++i.Poche
R
3

There is a reason for this: performance. i++ generates a copy, and that's a waste if you immediately discard it. Granted, the compiler can optimize away this copy if i is a primitive, but it can't if it isn't. See this question.

Rowe answered 23/11, 2010 at 22:41 Comment(6)
This is disingenous. In almost every single case, the performance of ++i and i++ is exactly the same.Maggard
@John: Not disingenuous at all. For iterator objects, the compiler has no reason to even expect some sort of equivalence between prefix and postfix increment (the class designer can make them perform arbitrarily different actions)--it must call the postfix form (with resulting copy). For heavyweight iterators and otherwise lightweight loops, the performance hit can be significant. As an example, what if i is not an int or a std::vector<int>::iterator, but instead a BigInteger or equivalent. The copy is unneccessary and should just be avoided, period.Slowpoke
@Drew: In that case, the programmer is going to know it (or should, anyway) and my disclaimer that "if you have to ask, it doesnt matter" wont apply. The question was about "normal for loop"s. Performance has nothing to do with it. Its all about personal style.Maggard
John Dibling: "Normal for loops" typically involve iterators.Albrecht
@John: Perhaps. I guess I just consider it a good habit to be in--there is no downside to always writing ++i, but there is (sometimes) a downside to writing i++.Slowpoke
@Drew: I don't dispute it being a good habit to be in. In fact I do the same thing.Maggard
E
2

As others have already noted, pre-increment is usually faster than post-increment for user-defined types. To understand why this is so, look at the typical code pattern to implement both operators:

Foo& operator++()
{
    some_member.increase();
    return *this;
}

Foo operator++(int dummy_parameter_indicating_postfix)
{
    Foo copy(*this);
    ++(*this);
    return copy;
}

As you can see, the prefix version simply modifies the object and returns it by reference.

The postfix version, on the other hand, must make a copy before the actual increment is performed, and then that copy is copied back to the caller by value. It is obvious from the source code that the postfix version must do more work, because it includes a call to the prefix version: ++(*this);

For built-in types, it does not make any difference as long as you discard the value, i.e. as long as you do not embed ++i or i++ in a larger expression such as a = ++i or b = i++.

Erythrite answered 23/11, 2010 at 22:51 Comment(1)
I think "must make a copy" is overstating it a bit. If the result is unused, and the operator and the copy constructor can both be completely inlined, as is commonly the case with iterators, then it should be a sitting duck for the optimizer to remove copy entirely - unused value with no side-effects. ++i does save you wondering whether the optimization was successful, and more importantly it just obviously makes more sense ;-)Apiculate
N
1

when you use postfix it instantiates on more object in memory. Some people say that it is better to use suffix operator in for loop

Nerin answered 23/11, 2010 at 22:40 Comment(0)
M
-1

Personal preference.

Usually. Sometimes it matters but, not to seem like a jerk here, but if you have to ask, it probably doesn't.

Maggard answered 23/11, 2010 at 22:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.