try - Lista de lanzamientos en desuso en C++ 11
try catch c++ (4)
La respuesta que dio Peter no llega al problema real de las especificaciones de excepción para el implementador y el usuario:
- Las especificaciones de excepción hacen que el programa finalice (o, más precisamente, llame a los manejadores de terminación) si el implementador no cumplió con la garantía de lanzar solo las excepciones definidas.
- Por lo tanto, al llamar a un método con una especificación de excepción, usted como usuario de la biblioteca está haciendo que su propio código sea más propenso a completar la falla / terminación. Si la función de biblioteca se queda sin memoria (std :: bad_alloc), no tendrá la oportunidad de capturar, sino que se terminará.
- Por lo tanto, no se logró el objetivo original de comunicar las opciones de falla más probables y pedirle a usted como usuario que las maneje.
- Como implementador en el otro lado, ya no puede llamar a ningún otro método que no tenga especificaciones de excepción, ya que esto podría hacer que cancele a sus interlocutores. Un lugar terrible para estar.
La conclusión es que C ++ debería haberse ido como lo hizo Java:
- Si llama a un método con una especificación de excepción y tiene una especificación de excepción, entonces debe capturar la excepción o especificarla en su propia especificación de excepción.
- El compilador aplica esto y ningún otro efecto de tiempo de ejecución.
Noexcept (ya que C ++ 11) sufre el mismo error conceptual, ya que también causará la terminación en tiempo de ejecución si la especificación no se adhiere también, es decir, un método que se declara no. Esto hace que no noexcept
imposible usar nada excepto para los casos más serios, pero los más contenidos (los constructores de movimientos vienen a la mente ).
Tal como puedo ver en cppreference , las listas de declaraciones clásicas de "lanzamiento" ahora están en desuso en C ++ 11. ¿Cuál es la razón para abandonar este mecanismo y cómo debo especificar qué excepciones genera una función mía?
Para un razonamiento más detallado, consulte: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3051.html
Como se expresó en el comentario del organismo nacional anterior, las especificaciones de excepción no han demostrado ser útiles en la práctica. Existen numerosas discusiones sobre los problemas con las especificaciones de excepción en C ++ (ver, por ejemplo, [Sutter02], [Boost03]), pero los principales problemas son:
- Comprobación en tiempo de ejecución: las especificaciones de excepción de C ++ se verifican en tiempo de ejecución en lugar de en tiempo de compilación, por lo que no ofrecen a los programadores garantías de que se hayan manejado todas las excepciones. El modo de falla en tiempo de ejecución (llamar a std :: unexpected ()) no se presta a la recuperación.
- Gastos generales en tiempo de ejecución: la verificación en tiempo de ejecución requiere que el compilador produzca código adicional que también dificulte las optimizaciones.
- Inutilizable en código genérico: dentro del código genérico, generalmente no es posible saber qué tipos de excepciones pueden generarse a partir de operaciones en argumentos de plantilla, por lo que no se puede escribir una especificación de excepción precisa.
En la práctica, solo son útiles dos formas de garantías de lanzamiento de excepciones: una operación puede lanzar una excepción (cualquier excepción) o una operación nunca lanzará ninguna excepción. El primero se expresa omitiendo la especificación de la excepción por completo, mientras que el último se puede expresar como throw () pero rara vez lo es, debido a consideraciones de rendimiento.
[N3050] introduce un nuevo tipo de especificación de excepción, noexcept, que especifica que la función no generará ninguna excepción. A diferencia de throw (), noexcept no requiere que el compilador introduzca un código para verificar si se produce una excepción. Más bien, si una función especificada como noexcept se sale a través de una excepción, el resultado es una llamada a std :: terminate ().
Con la introducción de noexcept, los programadores ahora pueden expresar los dos tipos de garantías de excepción que son útiles en la práctica, sin gastos adicionales. Por lo tanto, este documento propone desaprobar las especificaciones de excepciones "dinámicas", es decir, aquellas que se escriben como lanzamientos (type-id-listopt).
Producen código más lento y más grande, porque libc ++ tiene que verificar si alguna excepción que se propague fuera de una función viola su especificación de excepción y llama a std::unexpected
. Esto casi nunca es útil, y es peor que solo documentar las excepciones que una función te lanza.
Solo el formulario sin una lista throw () está en desuso. Los formularios sin el lanzamiento de lista faltante (int, excepción &) , etc. no están en desuso.