Po pierwsze:
do-while
Pętli nie jest taki sam jak while
-loop lub for
-loop.
while
a for
pętle mogą w ogóle nie uruchamiać treści pętli.
do-while
Pętla zawsze przebiega ciało pętli przynajmniej raz - pomija początkową sprawdzić stan.
To jest logiczna różnica. To powiedziawszy, nie wszyscy ściśle przestrzegają tego. Pętle while
lub są dość powszechne, for
nawet jeśli jest zagwarantowane, że zawsze będą się zapętlać co najmniej raz. (Szczególnie w językach z pętlami foreach ).
Aby uniknąć porównywania jabłek i pomarańczy, będę zakładał, że pętla zawsze będzie działać co najmniej raz. Ponadto nie będę for
ponownie wspominał o pętlach, ponieważ zasadniczo sąwhile
pętlami z odrobiną cukru składniowego dla licznika pętli.
Odpowiem więc na pytanie:
Jeśli while
pętla jest gwarantowana co najmniej raz, czy użycie do-while
pętli powoduje wzrost wydajności .
A do-while
pomija pierwszą kontrolę stanu. Jest więc jedna gałąź mniej i jeden warunek mniej do oceny.
Jeśli sprawdzenie tego warunku jest drogie i wiesz, że masz gwarancję wykonania pętli co najmniej raz, do-while
pętla może być szybsza.
I chociaż jest to uważane w najlepszym przypadku za mikro-optymalizację, jest to taka, której kompilator nie zawsze może zrobić: w szczególności, gdy kompilator nie jest w stanie udowodnić, że pętla zawsze wejdzie co najmniej raz.
Innymi słowy, pętla while:
while (condition){
body
}
W praktyce to to samo:
if (condition){
do{
body
}while (condition);
}
Jeśli wiesz, że zawsze będziesz co najmniej raz zapętlić, ta instrukcja if jest zbędna.
Podobnie na poziomie zespołu, w ten sposób z grubsza kompilują się różne pętle, aby:
pętla do-while:
start:
body
test
conditional jump to start
pętla while:
test
conditional jump to end
start:
body
test
conditional jump to start
end:
Zwróć uwagę, że warunek został zduplikowany. Alternatywnym podejściem jest:
unconditional jump to end
start:
body
end:
test
conditional jump to start
... który zamienia zduplikowany kod na dodatkowy skok.
Tak czy inaczej, jest to nadal gorsze niż normalna do-while
pętla.
To powiedziawszy, kompilatorzy mogą robić, co chcą. A jeśli uda im się udowodnić, że pętla zawsze pojawia się raz, to wykonała pracę za Ciebie.
Ale sytuacja wygląda nieco dziwnie w przypadku konkretnego przykładu w pytaniu, ponieważ ma on pustą treść pętli. Ponieważ nie ma ciała, nie ma logicznej różnicy między while
ido-while
.
FWIW, przetestowałem to w Visual Studio 2012:
Z pustą treścią faktycznie generuje ten sam kod dla while
i do-while
. Więc ta część jest prawdopodobnie pozostałością po dawnych czasach, kiedy kompilatory nie były tak świetne.
Ale z niepustą treścią VS2012 udaje się uniknąć powielania kodu warunku, ale nadal generuje dodatkowy skok warunkowy.
To ironiczne, że chociaż przykład w pytaniu podkreśla, dlaczego do-while
pętla może być szybsza w ogólnym przypadku, sam przykład nie wydaje się przynosić żadnych korzyści dla nowoczesnego kompilatora.
Biorąc pod uwagę wiek komentarza, możemy tylko zgadywać, dlaczego miałby to znaczenie. Jest bardzo możliwe, że kompilatory w tym czasie nie były w stanie rozpoznać, że ciało było puste. (A jeśli tak, to nie wykorzystali informacji).