Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Guideline: while vs for

Disclaimer: I tried to search for similar question, however this returned about every C++ question... Also I would be grateful to anyone that could suggest a better title.

There are two eminent loop structure in C++: while and for.

  • I purposefully ignore the do ... while construct, it is kind of unparalleled
  • I know of std::for_each and BOOST_FOREACH, but not every loop is a for each

Now, I may be a bit tight, but it always itches me to correct code like this:

int i = 0;
while ( i < 5)
{
  // do stuff
  ++i; // I'm kind and use prefix notation... though I usually witness postfix
}

And transform it in:

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

The advantages of for in this example are multiple, in my opinion:

  1. Locality: the variable i only lives in the scope of the loop
  2. Pack: the loop 'control' is packed, so with only looking at the loop declaration I can figure if it is correctly formed (and will terminate...), assuming of course that the loop variable is not further modified within the body
  3. It may be inlined, though I would not always advised it (that makes for tricky bugs)

I have a tendency therefore not to use while, except perhaps for the while(true) idiom but that's not something I have used in a while (pun intended). Even for complicated conditions I tend to stick to a for construct, though on multiple lines:

// I am also a fan of typedefs
for (const_iterator it = myVector.begin(), end = myVector.end();
     it != end && isValid(*it);
     ++it)
{ /* do stuff */ }

You could do this with a while, of course, but then (1) and (2) would not be verified.

I would like to avoid 'subjective' remarks (of the kind "I like for/while better") and I am definitely interested to references to existing coding guidelines / coding standards.

EDIT:

I tend to really stick to (1) and (2) as far as possible, (1) because locality is recommended >> C++ Coding Standards: Item 18, and (2) because it makes maintenance easier if I don't have to scan a whole body loop to look for possible alterations of the control variable (which I takes for granted using a for when the 3rd expression references the loop variables).

However, as gf showed below, while do have its use:

while (obj.advance()) {}

Note that this is not a rant against while but rather an attempt to find which one of while or for use depending on the case at hand (and for sound reasons, not merely liking).

like image 761
Matthieu M. Avatar asked Oct 21 '09 11:10

Matthieu M.


2 Answers

Not all loops are for iteration:

while(condition) // read e.g.: while condition holds
{
}

is ok, while this feels forced:

for(;condition;)
{
}

You often see this for any input sources.

You might also have implicit iteration:

while(obj.advance())
{
}

Again, it looks forced with for.

Additionally, when forcing for instead of while, people tend to misuse it:

for(A a(0); foo.valid(); b+=x); // a and b don't relate to loop-control
like image 122
Georg Fritzsche Avatar answered Sep 29 '22 13:09

Georg Fritzsche


Functionally, they're the same thing, of course. The only reason to differentiate is to impart some meaning to a maintainer or to some human reader/reviewer of the code.

I think the while idiom is useful for communicating to the reader of the code that a non-linear test is controlling the loop, whereas a for idiom generally implies some kind of sequence. My brain also kind of "expects" that for loops are controlled only by the counting expression section of the for statement arguments, and I'm surprised (and disappointed) when I find someone conditionally messing with the index variable inside the execution block.

You could put it in your coding standard that "for" loops should be used only when the full for loop construct is followed: the index must be initialized in the initializer section, the index must be tested in the loop-test section, and the value of the index must only be altered in the counting expression section. Any code that wants to alter the index in the executing block should use a while construct instead. The rationale would be "you can trust a for loop to execute using only the conditions you can see without having to hunt for hidden statements that alter the index, but you can't assume anything is true in a while loop."

I'm sure there are people who would argue and find plenty of counter examples to demonstrate valid uses of for statements that don't fit my model above. That's fine, but consider that your code can be "surprising" to a maintainer who may not have your insight or brilliance. And surprises are best avoided.

like image 41
John Deters Avatar answered Sep 29 '22 11:09

John Deters