Поперше:
do-while
Петля не те ж саме , як while
-loop або for
-loop.
while
і for
цикли можуть взагалі не запускати тіло циклу.
- A
do-while
Цикл завжди виконується тіло циклу принаймні один раз - він пропускає першу перевірку умови.
Тож це логічна різниця. Тим не менш, не всі суворо цього дотримуються. Це досить часто для while
абоfor
циклів використовується навіть тоді, коли гарантується, що він завжди буде цикл хоча б один раз. (Особливо в мовах із циклами foreach .)
Тому, щоб уникнути порівняння яблук та апельсинів, я продовжуватиму, припускаючи, що цикл завжди буде працювати хоча б один раз. Крім того, я не буду згадуватиfor
цикли, оскільки це, по суті, while
цикли з трохи синтаксису цукру для лічильника циклів.
Тож я відповім на запитання:
Якщо while
цикл гарантовано повторюється принаймні один раз, чи є збільшення продуктивності від використанняdo-while
замість нього циклу.
A do-while
Пропускає першу перевірку умови. Отже, є одна гілка менше і одна менша умова для оцінки.
Якщо умова дорого перевіряється, і ви знаєте, що гарантовано повторите принаймні один раз, то do-while
цикл може бути швидшим.
І хоча це в кращому випадку вважається мікрооптимізацією, компілятор не завжди може це зробити: зокрема, коли компілятор не може довести, що цикл завжди ввійде хоча б один раз.
Іншими словами, цикл while:
while (condition){
body
}
Фактично такий самий, як цей:
if (condition){
do{
body
}while (condition);
}
Якщо ви знаєте, що завжди хоч раз будете циклічно повторюватись, цей оператор if буде стороннім.
Так само на рівні збірки, приблизно так компілюються різні цикли, щоб:
цикл do-while:
start:
body
test
conditional jump to start
while-loop:
test
conditional jump to end
start:
body
test
conditional jump to start
end:
Зверніть увагу, що умова продубльовано. Альтернативний підхід:
unconditional jump to end
start:
body
end:
test
conditional jump to start
... який обміняє дублікат коду для додаткового стрибка.
У будь-якому випадку, це все одно гірше звичайного do-while
циклу.
Тим не менш, компілятори можуть робити те, що хочуть. І якщо вони можуть довести, що цикл завжди входить один раз, то він зробив роботу за вас.
Але для конкретного прикладу у питанні все трохи дивно, оскільки він має порожнє тіло циклу. Оскільки немає тіла, немає логічної різниці між while
і do-while
.
FWIW, я тестував це у Visual Studio 2012:
З порожнім тілом він насправді генерує той самий код для while
і do-while
. Тож ця частина, швидше за все, є залишком старих часів, коли компілятори не були такими чудовими.
Але з непорожнім тілом VS2012 вдається уникнути дублювання коду умови, але все одно генерує додатковий умовний стрибок.
Тому іронічно, що, хоча приклад у питанні підкреслює, чому do-while
цикл може бути швидшим у загальному випадку, сам приклад, здається, не дає жодної користі для сучасного компілятора.
Враховуючи, скільки років був коментар, ми можемо лише здогадуватися, чому це мало значення. Цілком можливо, що укладачі того часу не були здатні визнати, що тіло порожнє. (Або якщо вони це зробили, вони не використовували інформацію.)