Why an Empty Loop Can Disappear

A compiler does not have to preserve every step written in a C++ program. It must preserve the program’s observable behavior—effects such as printing output, changing a volatile object, or performing certain synchronization operations. If a loop changes nothing the program can observe, its repeated execution may not count as behavior the compiler is required to preserve.

That matters when the loop never ends. If the compiler is allowed to assume the loop will eventually finish, it can reason that code after the loop is reachable and optimize accordingly. In some cases, it may remove the loop entirely. The resulting program can then behave very differently from what the programmer expected.

“No Side Effects” Has a Technical Meaning

A side effect is not simply any calculation. Adding numbers to a local variable that is never used, for example, may leave no observable trace; writing to a `volatile` object does leave one. Input and output, and certain atomic or synchronization operations, also affect what a program or other threads can observe.

C++’s rules about forward progress give implementations room to assume that execution makes progress. They do not mean every endless loop is automatically removed: details such as the loop’s form and whether it has observable effects matter. A loop explicitly written as an unconditional constant-expression loop, such as `for (;;) {}`, is treated differently from some loops whose continuation depends on a runtime condition.

Why the Rule Exists

Without this freedom, a compiler might have to preserve a loop that does nothing forever, even when that would prevent useful optimization of the surrounding code. The rule lets it reason about what a conforming program can do, rather than treating every written instruction as untouchable.

For programmers, the practical lesson is that a loop intended to wait or keep a thread alive needs a real, well-defined way to make progress. If it merely spins on an ordinary variable that never changes in the program’s visible behavior, optimization can turn the apparent wait into something else.