It's not just readability, it's also the closely-related but distinct maintainability, and concision, and scoping (esp. for files, locks, smart pointers etc.), and performance....
If we consider the for
loop, it:
allows some variables to be defined - in the for
loop's own scope - and initialised,
tests a control expression before entering the loop each time (including the first), and
has a statement that gets executed after each iteration and before re-testing the control expression, assuming no break
/return
/throw
/exit
/failed assert
etc., and regardless of whether the last statement in the body executed or whether a continue
statement executed; this statement is traditionally reserved for logically "advancing" some state "through" the processing, such that the next test of the control expression is meaningful.
That's very flexible and given the utility of more localised scopes to ensure earlier destructor invocation, can help ensure locks, files, memory etc. are released as early as possible - implicitly when leaving the loop.
If we consider a while
loop...
while (expression to test)
...
...it's functionally exactly equivalent to...
for ( ; expression to test; )
...
...but, it also implies to the programmer that there are no control variables that should be local to the loop, and that either the control "expression to test" inherently "progresses" through a finite number of iterations, loops forever if the test expression is hardcoded true
, or more complicated management of "progress" had to bed itself controlled and coordinated by the statements the while
controls.
In other words, a programmer seeing while
is automatically aware that they need to study the control expression more carefully, then possibly look more widely at both the surrounding scope/function and the contained statements, to understand the loop behaviour.
So, do
-while
? Well, writing code like this is painful and less efficient:
bool first_time = true;
while (first_time || ...)
{
first_time = false;
...
}
// oops... first_time still hanging around...
...compared to...
do
...
while (...);
Examples
While loop:
int i = 23;
while (i < 99)
{
if (f(i)) { ++i; continue; }
if (g(i)) break;
++i;
}
// oops... i is hanging around
For loop:
for (int i = 23; i < 99; ++i)
{
if (f(i)) continue;
if (g(i)) break;
}