amit singh
Soy muy consciente del hecho de que no se debe lanzar ninguna excepción en destructor.
Pero como parte de controlar este concepto, codifiqué este ejemplo: –
#include <iostream>
class A {
private:
int i;
public:
A() { i = 10; }
~A() { throw 30; }
};
int main(){
try{
A();
throw 10;
}
catch (int i) {
std::cout << i << std::endl;
std::cout << "exception caught" << std::endl;
}
}
Según tengo entendido, este programa debe finalizar llamando a std::terminate() ya que habrá dos excepciones al mismo tiempo. Pero, este programa está dando el siguiente resultado: –
30
exception caught
¿Puede alguien explicarme la lógica detrás de esto en cuanto a por qué esto no está terminando?
Vittorio Romeo
std::terminate
se llamará si se lanza una excepción durante apilar desenrollando. Eso significa que si se llama una excepción mientras se maneja otra excepcióndespués std::terminate
sera llamado.
En tu ejemplo, eso no sucede – A();
va a construir y inmediatamente destruir una instancia de A
. los throw 30
entonces será capturado correctamente.
Cambiando su código a:
int main(){
try{
A a; // begin `a` lifetime
throw 10; // | throw #0
// | end `a` lifetime
// throw #1
}
catch(int i){
cout<<i<<endl;
cout<<"exception caught"<<endl;
}
}
garantizará que std::terminate
sera llamado. En este caso, a
será destruido y arrojará mientras se maneja otra excepción.
Información Adicional:
-
StackOverflow: “lanzar excepciones de un destructor”
Tenga en cuenta que en C++ 11 y superiorsu fragmento de código llamará std::terminate
y proporcionarle una advertencia:
main.cpp: En el destructor ‘A::~A()’:
main.cpp:16:15: advertencia: throw siempre llamará a terminar()
[-Wterminate]throw 30; ^~
principal.cpp:16:15: nota: en C ++ 11, los destructores predeterminados son noexcept
Terminar llamado después de lanzar una instancia de ‘int’
bash: línea 7: 1505 Anulado (núcleo volcado) ./a.out
Como se ve en la salida del compilador, desde C++11 los destructores son implícitamente noexcept(true)
. Si desea evitar este comportamiento, simplemente puede marcarlos como noexcept(false)
. Ejemplo:
~A() noexcept(false)
{
throw 30;
}
-
Realmente
std::terminate
llamado con variable sin nombre también. De acuerdo aiostream.h
OP usa compilador antiguo– Eslava
23 de marzo de 2017 a las 12:52
-
@Slava: ese es un problema no relacionado. En C ++ 11, los destructores están implícitamente
noexcept
. Modificaré mi respuesta.– Vittorio Romeo
23 de marzo de 2017 a las 12:54
En tu ejemplo, A()
construir una variable temporal para A
luego lo destruye inmediatamente. De este modo throw 10;
nunca se ejecuta.
los throw
declaración que tiene lugar está en el destructor para A
. Al ejecutar A::~A()
, el programa no se está desenrollando (es decir, limpiando el estado de una excepción) en ese momento. Ver “Destructores que tiran” por ejemplo.
Por qué
throw 10;
se espera que se ejecute?– dmi
23 de marzo de 2017 a las 12:47
No se puede reproducir G++ 5.1.0: “terminar llamado después de lanzar una instancia de ‘int'”
– Richard Critten
23 de marzo de 2017 a las 12:48
Es bueno saber que no debes lanzar una excepción en destructor, pero ¿sabes por qué?
– Ankur
23 de marzo de 2017 a las 12:49
no se puede reproducir con clang
– Gualterio
23 de marzo de 2017 a las 12:50
No puede reproducirse ideone.com/7T91cF – terminar llamado después de lanzar una instancia de ‘int’
– Eslava
23 de marzo de 2017 a las 12:53