All over the web, code samples have for
loops which look like this:
for(int i = 0; i < 5; i++)
while I used the following format:
for(int i = 0; i != 5; ++i)
I do this because I believe it to be more efficient, but does this really matter in most cases?
I see plenty of answers using the specific code that was posted, and integer. However the question was specific to 'for loops', not the specific one mentioned in the original post.
I prefer to use the prefix increment/decrement operator because it is pretty much guaranteed to be as fast as the postfix operator, but has the possibility to be faster when used with non-primitive types. For types like integers it will never matter with any modern compiler, but if you get in the habit of using the prefix operator, then in the cases where it will provide a speed boost, you'll benefit from it.
I recently ran a static analysis tool on a large project (probably around 1-2 million lines of code), and it found around 80 cases where a postfix was being used in a case where a prefix would provide a speed benefit. In most of these cases the benefit was small because the size of the container or number of loops would usually be small, but in other cases it could potentially iterate over 500+ items.
Depending on the type of object being incremented/decremented, when a postfix occurs a copy can also occur. I would be curious to find out how many compilers will spot the case when a postfix is being used when its value isn't referenced, and thus the copy could not be used. Would it generate code in that case for a prefix instead? Even the static analysis tool mentioned that some of those 80 cases it had found might be optimized out anyway, but why take the chance and let the compiler decide? I don't find the prefix operator to be at all confusing when used alone, it only becomes a burden to read when it starts getting used, inline, as part of a logic statement:
Having to think about operator precedence shouldn't be necessary with simple logic.
Sure the code above takes an extra line, but it reads more clearly. But with a for loop the variable being altered is its own statement, so you don't have to worry about whether it's prefix or postfix, just like in the code block above, the
i++
is alone, so little thought is required as to what will happen with it, so this code block below is probably just as readable:As I've said, it doesn't matter all that much, but using the prefix when the variable is not being used otherwise in the same statement is just a good habit in my opinion, because at some point you'll be using it on a non-primitive class and you might save yourself a copy operation.
Just my two cents.
I switched to using
!=
some 20+ years ago after reading Dijkstra's book called "A Discipline of Programming". In his book Dijkstra observed that weaker continuation conditions lead to stronger post-conditions in loop constructs.For example, if we modify your construct to expose
i
after the loop, the post-condition of the fist loop would bei >= 5
, while the post-condition of the second loop is a much strongeri == 5
. This is better for reasoning about the program in formal terms of loop invariants, post-conditions, and weakest pre-conditions.I have decided to list the most informative answers as this question is getting a little crowded.
DenverCoder8's bench marking clearly deserves some recognition as well as the compiled versions of the loops by Lucas. Tim Gee has shown the differences between pre & post increment while User377178 has highlighted some of the pros and cons of < and !=. Tenacious Techhunter has written about loop optimizations in general and is worth a mention.
There you have my top 5 answers.
In generic code you should prefer the version with
!=
operator since it only requires youri
to be equally-comparable, while the<
version requires it to be relationally-comparable. The latter is a stronger requirement than the former. You should generally prefer to avoid stronger requrements when a weaker requirement is perfectly sufficient.Having said that, in your specific case if
int i
both will work equally well and there won't be any difference in performance.Everybody loves their micro-optimizations, but this would not make a difference as far as I can see. I compiled the two variations with g++ on for Intel processors without any fancy optimizations and the results are for
I think
jle
andjne
should translate to equally fast instructions on most architectures. So for performance, you should not distinguish between the two. In general, I would agree that the first one is a little safer and I also think more common.EDIT (2 years later): Since this thread recently got again a lot of attention, I would like to add that it will be difficult to answer this question generally. Which versions of code are more efficient is specifically not defined by the C-Standard [PDF] (and the same applies to C++ and probably also for C# ).
Section 5.1.2.3 Program execution
But it is reasonable to assume that a modern compiler will produce equally efficient code and I think that in only very rare cases will the loop-test and the counting expression be the bottleneck of a for-loop.
As for taste, I write
If the increment rule changes slightly you immediately have an infinite loop. I much prefer the first end condition.