compiler - Diferencia entre el especificador C++ 03 throw() C++ 11 noexcept
c++11 compiler (3)
Los especificadores de excepciones se desaprobaron porque los especificadores de excepciones generalmente son una idea terrible . noexcept
fue agregado porque es el uso razonablemente útil de un especificador de excepción: saber cuándo una función no lanzará una excepción. Por lo tanto, se convierte en una opción binaria: funciones que lanzarán y funciones que no lanzarán.
se agregó noexcept
lugar de simplemente eliminar todos los especificadores de tiro distintos de throw()
porque noexcept
es más poderoso. noexcept
puede tener un parámetro que compile-time resuelve en booleano. Si boolean es verdadero, entonces el noexcept
pega. Si boolean es falso, entonces el noexcept
no se pega y la función puede arrojarse.
Por lo tanto, puedes hacer algo como esto:
struct<typename T>
{
void CreateOtherClass() { T t{}; }
};
¿ CreateOtherClass
arroja excepciones? Podría, si el constructor predeterminado de T
puede. ¿Cómo lo contamos? Me gusta esto:
struct<typename T>
{
void CreateOtherClass() noexcept(is_nothrow_default_constructible<T>::value) { T t{}; }
};
Por lo tanto, CreateOtherClass()
lanzará iff arroja el constructor predeterminado del tipo dado. Esto soluciona uno de los principales problemas con los especificadores de excepciones: su incapacidad para propagarse en la pila de llamadas.
No puedes hacer esto con throw()
.
¿Hay alguna otra diferencia entre throw()
y noexcept
aparte del tiempo de ejecución comprobado y el de compilación, respectivamente?
El artículo de Wikipedia C ++ 11 sugiere que los especificadores de lanzamiento de C ++ 03 están en desuso.
¿Por qué es así, pero no es noexcept
suficientemente capaz para cubrir todo eso en tiempo de compilación?
[Nota: He referido esta pregunta y este artículo , pero no pude obtener la razón sólida de desaprobación.]
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 desde 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 std :: unexpected_handler actualmente instalado. El estándar std :: unexpected_handler llama a std :: terminate.
noexcept
no se comprueba en tiempo de compilación.
Una implementación no rechazará una expresión simplemente porque cuando se ejecute arrojará o podría lanzar una excepción que la función contenedora no permite.
Cuando una función que se declara noexcept
o throw()
intenta lanzar una excepción, la única diferencia es que una llama a terminate
y la otra llama a unexpected
y el último estilo de manejo de excepciones ha sido desaprobado.