2010-05-03 10 views
12

¿Alguien puede explicar las Especificaciones de excepción tal como se utilizan en C++?¿Alguien me puede explicar las especificaciones de excepción C++?

  • cuándo se utilizan (pocas veces he visto que se usa en el código)
  • ¿Cuáles son los pros y los contras (ventajas/desventajas) de utilizar especificaciones de excepción?
+4

El artículo definitivo sobre especificaciones de excepción: http://www.gotw.ca/publications/mill22.htm "Moral # 1: Nunca escriba una especificación de excepción. Moral # 2: Excepto posiblemente uno vacío, pero si yo fuera usted, yo evitaría incluso eso ". –

+0

http://www.gotw.ca/publications/mill22.htm –

+1

Mensaje del futuro: si alguien está leyendo esto hoy, uno debe saber que 'noexcept' puede mejorar el rendimiento del programa (en C++ 11) –

Respuesta

15

cuándo se utilizan (pocas veces he visto que se usa en el código)
esperemos que nunca, ya que están en desuso en la próxima versión de C++ debido a la normalización del próximo año.

¿Cuáles son los pros y los contras (ventajas/desventajas) del uso de especificaciones de excepción?
Brindan una forma para que los lectores de su código sepan exactamente qué excepciones pueden arrojar las funciones. El problema es que si se lanza una excepción inesperada (una que no está en la especificación), el programa terminará (de forma predeterminada).

+0

@James McNellis: Gracias :) –

-3

Básicamente, las especificaciones de excepción permiten al compilador optimizar la pila. La desventaja es que es una gran cantidad de especificaciones adicionales. Esto significa que comúnmente lo ve en el trabajo de la biblioteca, pero no tanto en el código de trabajo.

Creo que también está sucediendo algo de excepción de seguridad en tiempo de compilación, pero desde que nunca lo he usado, no estoy seguro.

+0

-1 : Las especificaciones de excepción no tienen absolutamente nada que ver con la pila. –

+1

http://msdn.microsoft.com/en-us/library/7f10tsf4(v=VS.80).aspx Supongo que cuando hablamos de objetos no enrollables, eso no tiene nada que ver con la pila. – Puppy

+0

Las especificaciones de excepción _can_ permiten cierta optimización del compilador del código generado; concretamente, una especificación de excepción vacía (es decir, 'throw()') puede permitir al compilador omitir ciertos códigos que de otro modo serían necesarios en función de la garantía del programador de que la función no arrojará una excepción. Cuánto ayuda, no tengo idea; Honestamente, no creo que alguna vez haya escrito una especificación de excepción en mi código. –

12

En general, se consideran una mala idea.

Dicen qué arrojará un método. La desventaja es que si ese método arroja algo más, tu aplicación finalizará. Entonces es una garantía, pero no de la misma manera que Java lo hace. Y agrega la sobrecarga de la inspección.

+3

+1: Pero nitpick: La aplicación no está terminada; la función inesperada es llamada. De forma predeterminada, eso significa que su aplicación ha finalizado, pero si tiene la función inesperada haciendo otra cosa que no sea otra cosa, es lo que sucederá. –

+0

+1 Las especificaciones de tiro están en desuso, pero desafortunadamente no se eliminaron en C++ 0x. @Billy: +1 para la explicación. Tengo 2 ejemplos que se me ocurren, de forma espontánea, donde es deseable una especificación de no-throw: destructores y funciones/métodos que se sabe que cruzan los límites de lenguaje/interoperabilidad, ya que las excepciones de C++ tienden a no funcionar bien con los demás. (y soy consciente de que C++ 0x dice que las especificaciones no-throw cambian y que la sintaxis actual está en desuso). –

+1

@Billy: la función inesperada puede generar algunos informes de error primero, pero ¿no tiene que finalizar el programa? IIRC está prohibido regresar de lo inesperado(). –

6

Lo importante es saber: las especificaciones de excepción están en desuso en la próxima revisión de C++, excepto para el especificador de no-tiro (throw()), que básicamente dice oficialmente "no las use".

Poner throw() después de una función significa que la función no arroja ninguna excepción. Si lo hace de todos modos, la aplicación se terminará (probablemente, se llama al controlador inesperado), por lo que el resto de la aplicación puede usar esa función sabiendo que no emitirá una excepción. Esto puede ser útil para escribir código de excepción.

Ejemplo:

void MyFunction() throw() // does not throw any exceptions 
{ 
    /* ... */ 
{ 
+3

La garantía de no tirar es muy importante. Especialmente para destructores. Aunque sería bueno si el compilador te advirtiera que tienes un método de no lanzar que potencialmente podría arrojar. –

+1

Observe que 'throw()' especifica la especificación de la excepción dinámica, mientras que 'noexcept' especifica la verificación del tiempo de compilación y permite optimizaciones.Si el método está marcado como 'throw()' no significa que no pueda arrojarse, por lo que el compilador debe generar algún código de comprobación y manejo de excepciones. Y en el caso de 'noexcept' simplemente no puede. El compilador no generará código redundante para las excepciones y no le permitirá compilar la función que arroja algunas excepciones (o cualquier función llamada arrojar dentro) y está marcada con 'noexcept'. –

+0

@Occulta Estoy bastante seguro de que una función marcada como 'noexcept' aún puede lanzar una excepción. – Navin

1

Indican al programador que excepciones serán lanzados desde esa función. Tienen la ventaja de que tienes la garantía de que no se pueden lanzar otras excepciones desde esa función. Sin embargo, no hay comprobación en tiempo de compilación de si la función realmente arroja alguna excepción que no sea la indicada en el especificador de tiro. En cambio, se verifica en tiempo de ejecución. Y si falla, se llama a unexpected(), que de manera predeterminada llama al abort(), que a su vez finaliza su programa. Entonces, a menos que realmente desee que su programa muera si lo arruina y se produce una excepción inesperada, probablemente sea una mala idea usarlos.

El único lugar donde realmente recomendaría su uso es en destructores. Es realmente malo si se lanza un destructor. Deberían nunca tiro.Por lo tanto, si usa throw() en un destructor para indicar que no puede lanzar una excepción, entonces sabrá que su programa morirá en lugar de continuar en el mal estado en que estaría después de que se haya lanzado una excepción desde un destructor.

Independientemente de eso, si utiliza cualquier tipo de especificador de tiro, debe asegurarse de que realmente desea que su programa muera si se infringe. Entonces, en términos generales, es mejor no usarlos.

Cuestiones relacionadas