2012-10-11 71 views
78

¿Hay alguna otra diferencia entre throw() y noexcept además de ser verificado en tiempo de ejecución y tiempo de compilación, respectivamente?Diferencia entre el especificador de C++ 03 throw() C++ 11 noexcept

Wikipedia C++11 El artículo sugiere que los especificadores de lanzamiento C++ 03 están en desuso.
¿Por qué es así, es noexcept capaz de cubrir todo eso en tiempo de compilación?

[Nota: me he referido this question y this article, pero no podía consiguió la razón sólida de desaprobación.]

+6

Acordar a este [buen artículo] (http://akrzemi1.wordpress.com/2011/06/10/using-noexcept/) también 'noexcept' puede incurrir en comprobaciones de tiempo de ejecución. La principal diferencia entre ellos es que romper 'noexcept' causa' std :: terminate' mientras rompe 'throw' provoca' std :: unexpected'. También un comportamiento de desenrollado de la pila ligeramente diferente en estos casos. – Fiktik

Respuesta

101

especificadores de excepción quedaron en desuso debido a exception specifiers are generally a terrible idea. Se agregó noexcept porque es el uso razonablemente útil de un especificador de excepciones: saber cuándo una función no generará una excepción. Por lo tanto, se convierte en una opción binaria: funciones que lanzarán y funciones que no lanzarán.

noexcept se ha agregado en lugar de eliminar todos los especificadores de tiro distintos de throw() porque noexcept es más potente. noexcept puede tener un parámetro que el tiempo de compilación resuelve en booleano. Si boolean es verdadero, entonces el noexcept se pega. Si boolean es falso, entonces el noexcept no se pega y la función puede arrojar.

Por lo tanto, se puede hacer algo como esto:

struct<typename T> 
{ 
    void CreateOtherClass() { T t{}; } 
}; 

¿El CreateOtherClass excepciones tiro? Podría, si el constructor predeterminado de T puede. ¿Cómo lo contamos? De esta manera:

struct<typename T> 
{ 
    void CreateOtherClass() noexcept(is_nothrow_default_constructible<T>::value) { T t{}; } 
}; 

Por lo tanto, si y sólo si CreateOtherClass() arrojará constructor por defecto del tipo dado lanza. Esto soluciona uno de los principales problemas con los especificadores de excepciones: su incapacidad para propagarse en la pila de llamadas.

No puede hacer esto con throw().

+0

+1 Respuesta útil, para mí de todos modos. Todavía estoy buscando una respuesta que diga por qué querría usar 'noexcept'. Nunca utilicé el especificador 'throw()', y estoy intentando determinar si 'noexcept' realmente proporciona algún beneficio (aparte de la documentación comprobada por el compilador). – hmjd

+0

Acabo de encontrar este http://stackoverflow.com/questions/10787766/when-should-i-really-use-noexcept ... – hmjd

+0

@hmjd: "* Todavía estoy buscando una respuesta que diga por qué querría usar noexcept . * "No encontrarás una respuesta a eso aquí porque esa * no es la pregunta * que se hizo. –

29

noexcept no se comprueba en tiempo de compilación.

Una implementación no debe rechazar una expresión simplemente porque cuando se ejecuta arroja o puede arrojar una excepción que la función contenedora no permite.

Cuando una función que se declara noexcept o throw() intentos de lanzar una excepción, la única diferencia es que uno llama terminate y las llamadas othe unexpected y este último estilo de manejo de excepciones efectivamente ya no se utiliza.

1

std :: unexpected() es invocado por el tiempo de ejecución de C++ cuando se infringe una especificación de excepción dinámica: se emite una excepción de una función cuya especificación de excepción prohíbe las excepciones de este tipo.

std :: unexpected() también se puede llamar directamente desde el programa.

En cualquier caso, std :: unexpected llama al estándar de instalación actual instalado: inesperado. El estándar std :: unexpected_handler llama a std :: terminate.

Cuestiones relacionadas