转自:http://blog.sina.com.cn/s/blog_86cee8660100vj49.html
throw的时候将被抛出的对象拷贝一份到专用的异常栈上,接着按声明时相反的顺序先析构掉本层作用域内的对象,再往上析构掉高层作用域中的对象,依次上推直到将throw之前的,在本函数中声明的所有对象都析构掉为止。然后再执行catch中的相关语句,最后才析构掉拷贝对象。
下面的代码用来说明对象析构顺序:
#include <Windows.h>
#include <exception>
#include <string>
using namespace std;
class TException : public std::exception {
public:
TException()
{
OutputDebugStringA("TException construct\n");
}
TException( const TException &te )
{
this->message_ = te.message_;
}
TException(const std::string& message) :
message_(message) {}
virtual ~TException() throw()
{
OutputDebugStringA("TException destruct\n");
}
virtual const char* what() const throw()
{
if ( message_.empty() )
{
return "Default TException.";
}
else
{
return message_.c_str();
}
}
protected:
std::string message_;
};
int main( void )
{
try
{
TException te;
throw te;
}
catch ( TException &te )
{
OutputDebugStringA( te.what() );
OutputDebugStringA( "\n");
}
return 0;
}
TException construct
TException destruct
Default TException.
TException destruct
所以在c++这种异常机制下异常对象会做两次析构操作,当catch参数不是引用而是值传递时(例:catch ( TException te ) ),这种情况的异常对象要做三次析构操作, 这往往程序员会忘记考虑这种情况导致未知情况发生。
所以,更好一点的c++异常机制是将异常对象分配在堆中,在catch语句中delete。
例子代码如下:
#include <Windows.h>
#include <exception>
#include <string>
using namespace std;
class TException : public std::exception {
public:
TException()
{
OutputDebugStringA("TException construct\n");
}
TException( const TException &te )
{
this->message_ = te.message_;
}
TException(const std::string& message) :
message_(message) {}
virtual ~TException() throw()
{
OutputDebugStringA("TException destruct\n");
}
virtual const char* what() const throw()
{
if ( message_.empty() )
{
return "Default TException.";
}
else
{
return message_.c_str();
}
}
protected:
std::string message_;
};
int main( void )
{
try
{
throw new TException();
}
catch ( TException *pe )
{
OutputDebugStringA( pe->what() );
OutputDebugStringA( "\n");
delete pe;
}
return 0;
}
输出结果:
TException construct
Default TException.
TException destruct