Tengo una pregunta sobre el uso de la sentencia goto en C++. Entiendo que este tema es controvertido y no me interesan los consejos o argumentos radicales (generalmente me alejo del uso de goto
). Más bien, tengo una situación específica y quiero entender si mi solución, que hace uso de la declaración goto, es buena o no. No me llamaría nuevo en C++, pero tampoco me clasificaría como programador de nivel profesional. La parte del código que generó mi pregunta gira en un bucle infinito una vez que comenzó. El flujo general de la rosca en pseudocódigo es el siguiente:Uso de goto para salir limpiamente de un bucle
void ControlLoop::main_loop()
{
InitializeAndCheckHardware(pHardware) //pHardware is a pointer given from outside
//The main loop
while (m_bIsRunning)
{
simulated_time += time_increment; //this will probably be += 0.001 seconds
ReadSensorData();
if (data_is_bad) {
m_bIsRunning = false;
goto loop_end;
}
ApplyFilterToData();
ComputeControllerOutput();
SendOutputToHardware();
ProcessPendingEvents();
while (GetWallClockTime() < simulated_time) {}
if (end_condition_is_satisified) m_bIsRunning = false;
}
loop_end:
DeInitializeHardware(pHardware);
}
El puntero se pasa en pHardware desde fuera del objeto ControlLoop y tiene un tipo polimórfico, por lo que no tiene mucho sentido para mí hacer uso de RAII y para crear y destruir la interfaz de hardware dentro de main_loop. Supongo que podría hacer que pHardware cree un objeto temporal que represente una especie de "sesión" o "uso" del hardware que podría limpiarse automáticamente al salir de main_loop, pero no estoy seguro de si esa idea lo haría más claro para alguien de lo contrario, cuál es mi intención. Solo habrá tres formas de salir del ciclo: la primera es si se leen datos incorrectos del hardware externo; el segundo es si ProcessPendingEvents() indica un aborto iniciado por el usuario, que simplemente hace que m_bIsRunning se vuelva falso; y el último es si la condición final se cumple en la parte inferior del ciclo. También debería señalar que main_loop podría iniciarse y finalizarse varias veces durante la vida del objeto ControlLoop, por lo que debería salir limpiamente con m_bIsRunning = false
después.
Además, me di cuenta de que podía utilizar la palabra reservada break, aunque la mayoría de estas funciones pseudocódigo llamadas dentro main_loop realmente no están encapsulados como funciones, simplemente porque tendrían que o bien tienen muchos argumentos o todos ellos necesitarían acceso a variables miembro Ambos casos serían más confusos, en mi opinión, que simplemente dejar main_loop como una función más larga, y debido a la longitud del ciclo big while, una afirmación como goto loop_end
parece ser más clara para mí.
Ahora para la pregunta: ¿Esta solución lo haría sentir incómodo si lo escribiera en su propio código? Me parece un poco erróneo, pero nunca antes utilicé la sentencia goto en el código C++, de ahí mi solicitud de ayuda de expertos. ¿Hay alguna otra idea básica que me falta que haga que este código sea más claro?
Gracias.
"no tiene mucho sentido para mí hacer uso de RAII" Siempre tiene sentido usar RAII. Siempre. Todo el tiempo. –
¿Por qué no utilizar 'break' aquí? –
Si solo hay un bucle que está rompiendo, use 'break'; es más limpio y más claro. Si tiene múltiples niveles de bucle, o si está dentro de un 'interruptor', y necesita salir de todos los bucles, entonces el 'goto' está bien. –