Cuando tiene varias declaraciones de devolución en una función, esto se conoce como "devolución anticipada". Si haces un Google search para "devolución anticipada", encontrarás un enlace tras otro que dice que es malo.
Digo tonterías.
Hay dos razones principales y una razón secundaria por la que las personas afirman que el regreso temprano es malo. Los revisaré y daré mi refutación en orden. Tenga en cuenta que esta es toda mi opinión y, en última instancia, debe decidir por usted mismo.
1) Motivo: Las devoluciones anticipadas dificultan la limpieza.
Refutación: para eso es RAII. Un programa bien diseñado no asignará recursos de tal manera que si la ejecución abandona el alcance de forma anticipada, esos recursos se filtrarán. En vez de hacer esto:
...
int foo()
{
MyComplexDevice* my_device = new MyComplexDevice;
// ...
if(something_bad_hapened)
return 0;
// ...
delete my_device;
return 42;
}
hacer esto:
int foo()
{
std::auto_ptr<MyComplexDevice> my_device(new MyComplexDevice);
if(something_bad_hapened)
return 0;
// ...
return 42;
}
Y pronto retorno no causará una pérdida de recursos. En la mayoría de los casos, ni siquiera necesitará usar auto_ptr
porque va a crear matrices o cadenas, en cuyo caso usará vector
, string
o algo similar.
Debe diseñar su código así de todos modos para mayor robustez, debido a la posibilidad de excepciones. Las excepciones son una forma de devolución anticipada, como una declaración explícita return
, y debe estar preparado para manejarlas. No puede manejar la excepción en foo()
, pero foo()
no debe tener fugas independientemente.
2) Motivo: Las devoluciones anticipadas hacen que el código sea más complejo. Refutación: los retornos iniciales realmente hacen que el código sea más simple.
Es una filosofía común que las funciones deben tener una responsabilidad. Estoy de acuerdo con eso. Pero la gente lleva esto demasiado lejos y concluye que si una función tiene múltiples rendimientos, debe tener más de una responsabilidad. (Extienden esto diciendo que las funciones nunca deben tener más de 50 líneas de longitud, o algún otro número arbitrario). Digo que no. El hecho de que una función tenga solo una responsabilidad, no significa que no tenga mucho que hacer para cumplir con esa responsabilidad.
Tomemos como ejemplo la apertura de una base de datos. Esa es una responsabilidad, pero está compuesta de muchos pasos, cada uno de los cuales podría salir mal. Abra la conexión. Iniciar sesión. Obtener un objeto de conexión & devolverlo. 3 pasos, cada uno de los cuales podría fallar Se podría descomponerlo en 3 sub-pasos, pero entonces, en lugar de tener un código como éste:
int foo()
{
DatabaseObject db = OpenDatabase(...);
}
podrás llegar a tener:
int foo()
{
Connection conn = Connect(...);
bool login = Login(...);
DBObj db = GetDBObj(conn);
}
Así que ha movido la realidad sólo supuestas responsabilidades múltiples a un punto más alto en la pila de llamadas.
3) Motivo: Los puntos de retorno múltiples no están orientados a objetos. Refutación: Esta es solo otra forma de decir "todos dicen que los retornos múltiples son malos, aunque realmente no sé por qué".
Visto de otra manera, esto es realmente solo un intento de meter todo en una caja con forma de objeto, incluso cuando no pertenece allí. Claro, tal vez la conexión es un objeto. Pero es el inicio de sesión? Un intento de inicio de sesión no es (IMO) un objeto. Es una operación. O un algoritmo. tratar de tomar este algoritmo y meterlo en una caja con forma de objeto es un intento gratuito en OOP, y solo dará como resultado un código que es más complejo, más difícil de mantener y posiblemente incluso menos eficiente.
2º tiene una declaración else innecesaria, no se está probando ninguna condición así que ¿para qué usarla? – DumbCoder
@DumbCoder: Un error tipográfico simple ... Lo he arreglado. –
-1: Subjetivo y propenso a comenzar una guerra de llamas. –