Cuando arroja ex, se copia en una ubicación de memoria especial utilizada para objetos de excepción lanzados. Dicha copia se lleva a cabo por el constructor de copia normal.
Esto se puede ver fácilmente desde este ejemplo:
#include <iostream>
void ThrowIt();
class TestException
{
public:
TestException()
{
std::cerr<<this<<" - inside default constructor"<<std::endl;
}
TestException(const TestException & Right)
{
(void)Right;
std::cerr<<this<<" - inside copy constructor"<<std::endl;
}
~TestException()
{
std::cerr<<this<<" - inside destructor"<<std::endl;
}
};
int main()
{
try
{
ThrowIt();
}
catch(TestException & ex)
{
std::cout<<"Caught exception ("<<&ex<<")"<<std::endl;
}
return 0;
}
void ThrowIt()
{
TestException ex;
throw ex;
}
Salida de ejemplo:
[email protected]:~/cpp/test$ g++ -O3 -Wall -Wextra -ansi -pedantic ExceptionStack.cpp -o ExceptionStack.x
[email protected]:~/cpp/test$ ./ExceptionStack.x
0xbf8e202f - inside default constructor
0x9ec0068 - inside copy constructor
0xbf8e202f - inside destructor
Caught exception (0x9ec0068)
0x9ec0068 - inside destructor
Por cierto, se puede ver aquí que la posición de memoria utilizada para el objeto lanzado (0x09ec0068) está definitivamente lejos de la del objeto original (0xbf8e202f): la pila, como de costumbre, tiene direcciones altas, mientras que la memoria utilizada para el objeto arrojado está bastante abajo en el espacio de direcciones virtuales. Aún así, este es un detalle de implementación, ya que, como se señaló en otras respuestas, el estándar no dice nada sobre dónde debería estar la memoria para el objeto arrojado y cómo debería asignarse.
¿Es correcto usar una referencia aquí? 'catch (SomeKindOfException & ex)' Creo que esto es peligroso, ya que no llama al constructor de copia y se obtiene acceso a un área de memoria que pertenece a la pila dealocated de f()! Supongo que esto debería ser correcto en su lugar: 'catch (SomeKindOfException ex)' – Dacav
Es correcto (y aún mejor - ver http://www.parashift.com/c++faq-lite/exceptions.html section 17.7) para atrapar por referencia. Como indican las respuestas a mi pregunta, la excepción que se captura no es el objeto basado en la pila, sino una copia que reside en un lugar diferente que puede sobrevivir al desenrollado de la pila, por lo tanto, no existe tal riesgo. –
Bueno, corrí un experimento ayer por la tarde y sí, es mucho mejor usar las referencias. Mira esto: http: // pastebin.com/8YQuNAux Si lo ejecuta, puede observar que la excepción se asigna dinámicamente (en el sentido de 'nuevo') en cada captura sin referencia: si utiliza las referencias, en cambio, se asigna solo una vez y se destruye automáticamente cuando el alcance está terminado. También creo que este comportamiento depende estrictamente del compilador. – Dacav