Ante todo:
Un do-whilebucle no es lo mismo que un whilebucle o un forbucle.
whiley los forbucles pueden no ejecutar el cuerpo del bucle en absoluto.
- Un
do-whilebucle siempre ejecuta el cuerpo del bucle al menos una vez; omite la verificación de condición inicial.
Entonces esa es la diferencia lógica. Dicho esto, no todos se adhieren estrictamente a esto. Es bastante común que se utilicen bucles for whileo forincluso cuando se garantiza que siempre se repetirá al menos una vez. (Especialmente en idiomas con bucles foreach ).
Entonces, para evitar comparar manzanas y naranjas, procederé asumiendo que el ciclo siempre se ejecutará al menos una vez. Además, no volveré a mencionar los forbucles, ya que son esencialmente whilebucles con un poco de azúcar de sintaxis para un contador de bucles.
Entonces estaré respondiendo a la pregunta:
Si whilese garantiza que un bucle se repita al menos una vez, ¿hay alguna ganancia de rendimiento al usar un do-whilebucle en su lugar?
A do-whileomite la primera comprobación de condición. Entonces, hay una rama menos y una condición menos para evaluar.
Si la condición es costosa de verificar y sabe que tiene la garantía de realizar un bucle al menos una vez, entonces un do-whilebucle podría ser más rápido.
Y aunque esto se considera una microoptimización en el mejor de los casos, es una que el compilador no siempre puede hacer: específicamente cuando el compilador no puede probar que el bucle siempre entrará al menos una vez.
En otras palabras, un ciclo while:
while (condition){
body
}
Es efectivamente lo mismo que esto:
if (condition){
do{
body
}while (condition);
}
Si sabe que siempre hará un bucle al menos una vez, esa instrucción if es extraña.
Del mismo modo, a nivel de ensamblaje, así es aproximadamente como se compilan los diferentes bucles para:
bucle de hacer mientras:
start:
body
test
conditional jump to start
bucle while:
test
conditional jump to end
start:
body
test
conditional jump to start
end:
Tenga en cuenta que la condición se ha duplicado. Un enfoque alternativo es:
unconditional jump to end
start:
body
end:
test
conditional jump to start
... que cambia el código duplicado por un salto adicional.
De cualquier manera, sigue siendo peor que un do-whilebucle normal .
Dicho esto, los compiladores pueden hacer lo que quieran. Y si pueden demostrar que el bucle siempre entra una vez, entonces ha hecho el trabajo por usted.
Pero las cosas son un poco extrañas para el ejemplo particular de la pregunta porque tiene un cuerpo de bucle vacío. Como no hay cuerpo, no hay diferencia lógica entre whiley do-while.
FWIW, probé esto en Visual Studio 2012:
Con el cuerpo vacío, en realidad genera el mismo código para whiley do-while. Así que esa parte probablemente sea un remanente de los viejos tiempos cuando los compiladores no eran tan buenos.
Pero con un cuerpo no vacío, VS2012 logra evitar la duplicación del código de condición, pero aún genera un salto condicional adicional.
Así que es irónico que, si bien el ejemplo de la pregunta resalta por qué un do-whilebucle podría ser más rápido en el caso general, el ejemplo en sí no parece ofrecer ningún beneficio en un compilador moderno.
Teniendo en cuenta la antigüedad del comentario, solo podemos adivinar por qué sería importante. Es muy posible que los compiladores en ese momento no fueran capaces de reconocer que el cuerpo estaba vacío. (O si lo hicieron, no usaron la información).