Historia de la pregunta:
El mecanismo de manejo de excepciones se introdujo en C++ para proporcionar un manejo de errores más robusto y estructurado, en contraste con los códigos de retorno. Con los años, la sintaxis se ha ampliado y han surgido especificadores como noexcept para controlar la cancelación de lanzamiento de excepciones desde funciones.
Problema:
Un manejo incorrecto de excepciones a menudo conduce a fugas de memoria, comportamientos indefinidos o caídas de aplicaciones. Si no se considera el lanzamiento de excepciones desde constructores, destructores o al trabajar con recursos, surge un problema serio con el estado del programa.
Solución:
La sintaxis básica es el uso de try-catch. Las excepciones pueden ser de cualquier tipo, pero se recomienda heredar las personalizadas de std::exception. La palabra clave noexcept (C++11+) indica que la función no debería lanzar excepciones; lanzar excepciones desde una función noexcept invoca std::terminate().
Ejemplo de código:
#include <iostream> #include <stdexcept> void func() noexcept(false) { throw std::runtime_error("Error!"); } int main() { try { func(); } catch(const std::exception& ex) { std::cout << ex.what(); } }
Características clave:
¿Es aceptable lanzar excepciones en destructores?
No, lanzar una excepción desde un destructor durante el desensamblaje de la pila lleva a std::terminate(). Las excepciones en el destructor deben ser atrapadas dentro del propio destructor.
¿Qué sucede si se lanza una excepción desde una función noexcept?
Se invocará std::terminate, el programa finalizará de manera abrupta. noexcept es un contrato estricto.
¿Se pueden atrapar excepciones por valor? ¿Por qué es peligroso?
Se pueden atrapar por valor, pero el objeto se copia (object slicing). Se recomienda usar const &.
Ejemplo de código:
try { throw std::out_of_range("err"); } catch (const std::exception& e) { /* ... */ }
El código lanzaba excepciones en destructores de recursos; al finalizar de manera abrupta, la pila no se desensamblaba correctamente y los recursos quedaban como fugas.
Pros:
Contras:
Los métodos críticos fueron marcados como noexcept, los destructores manejaban todas las excepciones internamente. Se usaban catch por referencia, y todos los errores se registraban.
Pros:
Contras: