When the body must run first

Some tasks need to happen at least once before you can decide whether to continue. Consider a password prompt:

#include <iostream>
#include <string>

int main()
{
    std::string password{};

    // We must ask for the password before we can check it
    std::cout << "Enter password: ";
    std::getline(std::cin, password);

    while (password != "secret123")
    {
        std::cout << "Incorrect. Try again: ";
        std::getline(std::cin, password);
    }

    std::cout << "Access granted!\n";

    return 0;
}

This works, but notice the duplication - we prompt and read input twice. Once before the loop and once inside. That's awkward and violates the DRY principle (Don't Repeat Yourself).

The do-while statement

C++ provides a loop that guarantees at least one execution before checking the condition:

do
    statement;
while (condition);

The do-while statement executes its body first, then evaluates the condition. If true, it repeats. If false, the loop ends.

Here's the password example rewritten:

#include <iostream>
#include <string>

int main()
{
    std::string password{};

    do
    {
        std::cout << "Enter password: ";
        std::getline(std::cin, password);
    }
    while (password != "secret123");

    std::cout << "Access granted!\n";

    return 0;
}

No duplication. The prompt and input happen once per attempt, and we naturally check afterward whether to continue.

Execution order

The key difference from while loops is when the condition gets checked:

While loop: condition -> body -> condition -> body -> ... Do-while loop: body -> condition -> body -> condition -> ...

This means a while loop might execute zero times (if the condition is initially false), but a do-while always executes at least once.

int count{ 0 };

while (count > 0)    // Condition false immediately
{
    std::cout << "While: " << count << '\n';
    --count;
}
// Prints nothing

do
{
    std::cout << "Do-while: " << count << '\n';
    --count;
}
while (count > 0);   // Condition checked after first execution
// Prints: Do-while: 0

Practical example: rolling dice

Games often need the player to roll until achieving a target. You must roll at least once before knowing the result:

#include <iostream>
#include <random>

int rollDie()
{
    static std::mt19937 rng{ std::random_device{}() };
    static std::uniform_int_distribution<int> dist{ 1, 6 };
    return dist(rng);
}

int main()
{
    int roll{};
    int attempts{ 0 };

    do
    {
        roll = rollDie();
        ++attempts;
        std::cout << "Rolled: " << roll << '\n';
    }
    while (roll != 6);

    std::cout << "Got a 6 after " << attempts << " attempts!\n";

    return 0;
}

Output might be:

Rolled: 2
Rolled: 4
Rolled: 1
Rolled: 6
Got a 6 after 4 attempts!

You can't know whether you rolled a 6 until you actually roll. The do-while captures this "act then check" pattern naturally.

Variable scope matters

Variables declared inside the do block are destroyed before the condition is evaluated:

do
{
    int value{ getValue() };  // Created here
    process(value);
}  // value destroyed here
while (value > 0);  // Error: value doesn't exist!

Declare any variable needed in the condition outside the do block:

int value{};  // Declared outside
do
{
    value = getValue();
    process(value);
}
while (value > 0);  // Works: value still exists

This differs from for loops, where the loop variable can be declared in the initialization and used in the condition.

Numeric input validation

Validating user input is a classic do-while use case:

#include <iostream>

int main()
{
    int month{};

    do
    {
        std::cout << "Enter month (1-12): ";
        std::cin >> month;

        if (month < 1 || month > 12)
            std::cout << "Invalid month. ";
    }
    while (month < 1 || month > 12);

    std::cout << "You selected month " << month << '\n';

    return 0;
}

We must get input before we can validate it. The do-while handles this naturally.

The visibility concern

One criticism of do-while loops is that the condition appears at the bottom, making it less visible:

do
{
    // 20 lines of code...
    // ...
    // ...
    processData();
    updateState();
    // ...
}
while (shouldContinue());  // Easy to miss when scanning code

With a while loop, the condition is immediately visible at the top. Some developers avoid do-while entirely for this reason. Others use it sparingly for cases where it genuinely fits better.

Best Practice
Prefer while loops when either would work. Reserve do-while for cases where you genuinely need the body to execute before the first condition check.

Converting between while and do-while

Any do-while can be converted to a while by duplicating the body before the loop:

// Do-while version
do
{
    promptAndRead();
}
while (!isValid());

// Equivalent while version
promptAndRead();        // Duplicated before loop
while (!isValid())
{
    promptAndRead();
}

The do-while is cleaner when the body must run first. But if you can initialize your condition variable to a value that causes the loop to enter, a while loop works fine:

bool done{ false };     // Initialize to cause entry
while (!done)
{
    // process...
    done = checkIfDone();
}

Summary

  • Do-while loops execute their body at least once, then check the condition
  • Execution order is body -> condition -> body -> condition (unlike while's condition-first approach)
  • Variable scope requires declaring condition-dependent variables outside the do block
  • Common use cases include input validation and any "act then check" scenario
  • Visibility concerns make do-while less popular since the condition is at the bottom
  • Prefer while loops when given a choice; use do-while only when guaranteed first execution is genuinely needed