Zuerst:
Eine do-while
Schleife ist nicht dasselbe wie eine while
Schleife oder eine for
Schleife.
while
und for
Schleifen führen den Schleifenkörper möglicherweise überhaupt nicht aus.
- Eine
do-while
Schleife führt den Schleifenkörper immer mindestens einmal aus - sie überspringt die Anfangszustandsprüfung.
Das ist also der logische Unterschied. Das heißt, nicht jeder hält sich strikt daran. Es ist durchaus üblich, dass while
oder for
Schleifen verwendet werden, auch wenn garantiert ist, dass sie immer mindestens einmal wiederholt werden. (Besonders in Sprachen mit foreach- Schleifen.)
Um einen Vergleich von Äpfeln und Orangen zu vermeiden, gehe ich davon aus, dass die Schleife immer mindestens einmal ausgeführt wird. Außerdem werde ich for
Loops nicht noch einmal erwähnen , da es sich im Wesentlichen um while
Loops mit etwas Syntaxzucker für einen Loop-Zähler handelt.
Also werde ich die Frage beantworten:
Wenn while
garantiert wird, dass eine Schleife mindestens einmal wiederholt wird, gibt es einen Leistungsgewinn durch die Verwendung einer do-while
Schleife.
A do-while
überspringt die erste Zustandsprüfung. Es gibt also einen Zweig weniger und eine Bedingung weniger zu bewerten.
Wenn die Überprüfung der Bedingung teuer ist und Sie wissen, dass Sie garantiert mindestens einmal eine do-while
Schleife ausführen, kann eine Schleife schneller sein.
Und obwohl dies bestenfalls als Mikrooptimierung angesehen wird, kann der Compiler dies nicht immer tun: Insbesondere, wenn der Compiler nicht nachweisen kann, dass die Schleife immer mindestens einmal eintritt.
Mit anderen Worten, eine while-Schleife:
while (condition){
body
}
Ist effektiv das gleiche wie das:
if (condition){
do{
body
}while (condition);
}
Wenn Sie wissen, dass Sie immer mindestens einmal eine Schleife ausführen, ist diese if-Anweisung irrelevant.
Auf Assembly-Ebene werden die verschiedenen Schleifen auf folgende Weise kompiliert:
do-while-Schleife:
start:
body
test
conditional jump to start
while-Schleife:
test
conditional jump to end
start:
body
test
conditional jump to start
end:
Beachten Sie, dass die Bedingung dupliziert wurde. Ein alternativer Ansatz ist:
unconditional jump to end
start:
body
end:
test
conditional jump to start
... der den doppelten Code gegen einen zusätzlichen Sprung eintauscht.
In jedem Fall ist es immer noch schlimmer als eine normale do-while
Schleife.
Compiler können jedoch tun, was sie wollen. Und wenn sie beweisen können, dass die Schleife immer einmal eintritt, hat sie die Arbeit für Sie erledigt.
Aber für das jeweilige Beispiel in der Frage sind die Dinge etwas seltsam, weil es einen leeren Schleifenkörper hat. Da es keinen Körper gibt, gibt es keinen logischen Unterschied zwischen while
und do-while
.
FWIW, ich habe dies in Visual Studio 2012 getestet:
Mit dem leeren Körper wird tatsächlich der gleiche Code für while
und generiert do-while
. Dieser Teil ist wahrscheinlich ein Überbleibsel der alten Zeiten, als Compiler nicht so großartig waren.
Mit einem nicht leeren Körper schafft es VS2012 jedoch, eine Verdoppelung des Bedingungscodes zu vermeiden, erzeugt aber dennoch einen zusätzlichen bedingten Sprung.
Es ist also ironisch, dass das Beispiel in der Frage zwar zeigt, warum eine do-while
Schleife im allgemeinen Fall schneller sein könnte, das Beispiel selbst jedoch für einen modernen Compiler keinen Nutzen zu bringen scheint.
Wenn man bedenkt, wie alt der Kommentar war, können wir nur raten, warum er wichtig ist. Es ist sehr wahrscheinlich, dass die Compiler zu diesem Zeitpunkt nicht erkennen konnten, dass der Körper leer war. (Oder wenn doch, haben sie die Informationen nicht verwendet.)