iammilind
¿Hay alguna diferencia entre throw()
y noexcept
además de ser verificado en tiempo de ejecución y tiempo de compilación respectivamente?
Este artículo de Wikipedia C++11 sugiere que los especificadores de lanzamiento de C++03 están en desuso.
¿Por qué tan… es el noexcept
lo suficientemente capaz como para cubrir todo eso en tiempo de compilación?
Nota: Revisé esta pregunta y Este artículopero no pudo determinar el motivo sólido de su desaprobación.
Nicolás Bolas
Los especificadores de excepción quedaron en desuso porque los especificadores de excepción son generalmente una idea terrible. noexcept
se agregó porque es el único 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 elección binaria: funciones que arrojarán y funciones que no arrojarán.
noexcept
se agregó en lugar de simplemente eliminar todos los especificadores de lanzamiento que no sean throw()
porque noexcept
es más poderoso noexcept
puede tener un parámetro que se resuelve en tiempo de compilación en un valor booleano. Si el booleano es verdadero, entonces el noexcept
palos Si el booleano es falso, entonces el noexcept
no se pega y la función puede fallar.
Por lo tanto, puedes hacer algo como esto:
struct<typename T>
{
void CreateOtherClass() { T t{}; }
};
Lo hace CreateOtherClass
lanzar excepciones? Podría, si T
El constructor predeterminado de can. ¿Cómo lo decimos? Me gusta esto:
struct<typename T>
{
void CreateOtherClass() noexcept(is_nothrow_default_constructible<T>::value) { T t{}; }
};
Por lo tanto, CreateOtherClass()
arrojará si el constructor predeterminado del tipo dado arroja. Esto soluciona uno de los principales problemas con los especificadores de excepción: su incapacidad para propagarse en la pila de llamadas.
no puedes hacer esto con throw()
.
-
+1 Respuesta útil, para mí de todos modos. Sigo buscando una respuesta que diga por qué querría usar
noexcept
. nunca uséthrow()
especificador, alguna vez y estoy tratando de determinar sinoexcept
en realidad proporciona algún beneficio (aparte de la documentación verificada por el compilador).– hmjd
20 de febrero de 2013 a las 14:16
-
Sí, lo sé. solo estaba investigando
noexcept
y leyendo algunas preguntas/respuestas al respecto. La razón más importante que encontré fue que algunos (posiblemente todos) de los contenedores STL no usarán el constructor de movimiento si no se declara comonoexcept
que no me di cuenta.– hmjd
20 de febrero de 2013 a las 21:11
-
@NicolBolas está de acuerdo. pero si noexcept fuera una garantía, el compilador podría verificar si una función puede arrojar o no un destructor. Pudiendo así advertir a un programador que una función es noexcept o no.
– Alejandro Ah
26 de agosto de 2013 a las 10:47
-
@NicolBolas las llamadas en tiempo de ejecución
std::terminate
. cual es MUCHO PEOR! el código puede colarse en versiones que tienen funciones marcadasnoexcept
y en tiempo de ejecución (es decir, en los sitios de los clientes) se detectan infracciones. Quise decir que el compilador garantiza generar código que no tirar excepciones en primer lugar.– Alejandro Ah
26 de agosto de 2013 a las 11:58
-
@NicolBolas: Otra diferencia que vale la pena señalar. Si una función está marcada
throws()
entonces, si se lanza una excepción, la pila debe ser desenrollado hasta el alcance de esa función (por lo que todas las variables automáticas en la función se destruyen) en cuyo puntoterminate()
se llama (a través deunexpected()
). Si una función está marcadanoexcept
luego, si se lanza una excepción, se llama a terminar (el desenrollado de la pila es un detalle definido por la implementación).– Martín York
17/09/2013 a las 11:39
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 podría arrojar 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 uno llama terminate
y las otras llamadas unexpected
y el último estilo de manejo de excepciones ha quedado efectivamente en desuso.
-
Pero si una función virtual tiene
throw()
/noexcept
la verificación del tiempo de compilación garantiza que también haya un anulador.– chico curioso
28 de octubre de 2019 a las 4:56
ma13
std::unexpected()
es llamado por el tiempo de ejecución de C++ cuando se viola una especificación de excepción dinámica: se lanza 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 actualmente instalado std::unexpected_handler
. El valor por defecto std::unexpected_handler
llamadas std::terminate
.
De acuerdo a esto Buen articulo además
noexcept
puede incurrir en controles de tiempo de ejecución. La principal diferencia entre ellos es que rompernoexcept
causasstd::terminate
mientras se rompethrow
causasstd::unexpected
. También un comportamiento de desenrollado de pila ligeramente diferente en estos casos.– Fiktik
11 de octubre de 2012 a las 6:17
No hay nada de “tiempo de compilación” verificado con algunas especificaciones de excepción que sea “tiempo de ejecución” verificado en otros. Es solo un mito creado por los oponentes de las especificaciones de excepción de C++.
– chico curioso
1 de noviembre de 2019 a las 8:12