++i or i++ in for loops ??
Solution 1
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.
Solution 2
++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.
Solution 3
++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.
Solution 4
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.
Solution 5
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.
Ismail Marmoush
You can check my website and blog https://marmoush.com
Updated on July 08, 2022Comments
-
Ismail Marmoush almost 2 years
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 writingi++
? -
John Dibling over 13 yearsThis is disingenous. In almost every single case, the performance of
++i
andi++
is exactly the same. -
Drew Hall over 13 yearsThat's probably true for int-like indices, but not generally true for iterators and other objects that might act as indices.
-
rtpg over 13 yearsdoesn't i++ and ++i call the same operator?
-
SingleNegationElimination over 13 yearsAlthough 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. -
Oliver Charlesworth over 13 years@Token: I agree in principle. However,
i++
is somewhat idiomatic in C code; if you regularly use both languages, it can get confusing... -
Jim Mischel over 13 yearsPardon 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
? -
fredoverflow over 13 yearsNo,
++i
callsi.operator++()
andi++
callsi.operator(int)
. See my answer for implementation details. -
Drew Hall over 13 years@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.
-
Steve Jessop over 13 years@Jim: the compiler has to call the relevant operator overload (
operator++()
oroperator++(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". -
Drew Hall over 13 years@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.
-
Jim Mischel over 13 yearsegads, 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.
-
John Dibling over 13 years@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.
-
Steve Jessop over 13 yearsI 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 ;-) -
M2tM over 13 yearsJohn Dibling: "Normal for loops" typically involve iterators.
-
Drew Hall over 13 years@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++.
-
John Dibling over 13 years@Drew: I don't dispute it being a good habit to be in. In fact I do the same thing.
-
Martin York over 13 yearsThe 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.
-
sbi over 13 years@Oli: Heavens forbid that code being idiomatic in C would be a good reason to use it in C++ as well!
-
Ajk_P over 9 years100% 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.
-
s g about 8 yearsGreat and succinct example
-
Mouradif over 7 yearsI want to upvote your answer but then it wont be rated 42 anymore
-
wizzwizz4 almost 7 years@KiJéy You can come back to do it now. (But then it won't be rated 64 anymore...)
-
Mouradif almost 7 years@wizzwizz4 let's get this to 128