Tout d'abord:
Une do-while
boucle n'est pas la même chose qu'une while
-loop ou une for
-loop.
while
et les for
boucles peuvent ne pas exécuter du tout le corps de la boucle.
- Une
do-while
boucle exécute toujours le corps de la boucle au moins une fois - elle ignore la vérification de la condition initiale.
Voilà donc la différence logique. Cela dit, tout le monde n'y adhère pas strictement. Il est assez courant d' utiliser des boucles while
ou des for
boucles même s'il est garanti qu'elles boucleront toujours au moins une fois. (Surtout dans les langues avec des boucles foreach .)
Donc, pour éviter de comparer des pommes et des oranges, je vais continuer en supposant que la boucle s'exécutera toujours au moins une fois. De plus, je ne mentionnerai plus les for
boucles car ce sont essentiellement des while
boucles avec un peu de sucre de syntaxe pour un compteur de boucles.
Je vais donc répondre à la question:
Si une while
boucle est garantie de boucler au moins une fois, y a-t-il un gain de performance en utilisant une do-while
boucle à la place?
A do-while
ignore le premier contrôle de condition. Il y a donc une branche de moins et une condition de moins à évaluer.
Si la condition est coûteuse à vérifier et que vous savez que vous êtes assuré de faire une boucle au moins une fois, une do-while
boucle pourrait être plus rapide.
Et bien que cela soit considéré comme une micro-optimisation au mieux, c'est une que le compilateur ne peut pas toujours faire: en particulier lorsque le compilateur est incapable de prouver que la boucle entrera toujours au moins une fois.
En d'autres termes, une boucle while:
while (condition){
body
}
Est effectivement le même que celui-ci:
if (condition){
do{
body
}while (condition);
}
Si vous savez que vous bouclerez toujours au moins une fois, cette instruction if est étrangère.
De même, au niveau de l'assemblage, c'est à peu près comment les différentes boucles se compilent pour:
boucle do-while:
start:
body
test
conditional jump to start
boucle while:
test
conditional jump to end
start:
body
test
conditional jump to start
end:
Notez que la condition a été dupliquée. Une autre approche est:
unconditional jump to end
start:
body
end:
test
conditional jump to start
... qui échange le code en double contre un saut supplémentaire.
Quoi qu'il en soit, c'est encore pire qu'une do-while
boucle normale .
Cela dit, les compilateurs peuvent faire ce qu'ils veulent. Et s'ils peuvent prouver que la boucle entre toujours une fois, alors il a fait le travail pour vous.
Mais les choses sont un peu bizarres pour l'exemple particulier de la question car il a un corps de boucle vide. Puisqu'il n'y a pas de corps, il n'y a pas de différence logique entre while
et do-while
.
FWIW, j'ai testé ceci dans Visual Studio 2012:
Avec le corps vide, il génère en fait le même code pour while
et do-while
. Donc, cette partie est probablement un vestige de l'ancien temps où les compilateurs n'étaient pas aussi bons.
Mais avec un corps non vide, VS2012 parvient à éviter la duplication du code de condition, mais génère toujours un saut conditionnel supplémentaire.
Il est donc ironique que, bien que l'exemple de la question montre pourquoi une do-while
boucle pourrait être plus rapide dans le cas général, l'exemple lui-même ne semble pas apporter d'avantages sur un compilateur moderne.
Compte tenu de l'âge du commentaire, nous ne pouvons que deviner pourquoi il serait important. Il est très possible que les compilateurs de l'époque n'aient pas été capables de reconnaître que le corps était vide. (Ou s'ils l'ont fait, ils n'ont pas utilisé les informations.)