引发-捕获异常机制与传递函数参数机制的差异的问题
针对引发-捕获异常机制,我设计了如下代码:
//自定义异常类
class MyException{
public:
char str_what[80];
int what;
MyException(){*str_what = 0;what = 0;cout<<"This is MyException()"<<endl;}
MyException(char *s,int e){
strcpy(str_what,s);
what = e;
cout<<"This is MyException(char *s,int e)"<<endl;
}
~MyException() {cout<<"This is ~MyException()"<<endl;}
};
//主程序代码
int _tmain(int argc, _TCHAR *argv[])
{
int i;
try{
cout<<"Enter a positive number:";
cin>>i;
if (i<0) {
MyException opps("Not positive",i);
throw opps;
}
}
catch(MyException &e){
cout<<e.str_what<<": ";
cout<<e.what<<"\n";
}
return 0;
}
书(《C++ Primer Plus(第四版)中文版》,[美] Stephen Prata著,孙建春、韦强等译, 人民邮电出版社2002年11月出版)上的意思是:引发-捕获异常机制与传递函数参数机制很相似,但有一些区别,最主要的就是编译器总是在引发异常的时候创建临时拷贝。所以在上述代码中,尽管使用了引用参数,e仍然将指向opps的一个拷贝而不是opps本身。所以输出(包含了用户的输入)是:
Enter a positive number:-12
This is MyException(char *s,int e)
This is ~MyException()
Not positive: -12
This is ~MyException()
Press any key to continue
这表明构造函数被调用了一次而析构函数被调用两次,这是因为编译器使用按位拷贝生成了opps的一个拷贝。
如果将最关键的那一句“catch(MyException &e)”改为“catch(MyException e)”,使用按值传递参数,输出就变为:
Enter a positive number:-12
This is MyException(char *s,int e)
This is ~MyException()
Not positive: -12
This is ~MyException()
This is ~MyException()
Press any key to continue
这表明构造函数被调用了一次而析构函数被调用三次!!
我想请教各位:
为何析够函数会比构造函数多被调用两次?是因为编译器使用按位拷贝生成了opps的两个拷贝吗(这是我能想到的唯一解释)?编译器为何要这样做呢(既浪费时间又浪费资源)?为何不像使用引用参数那样只生成一个拷贝呢?引发-捕获异常机制与传递函数参数机制的这种差别是不是因为使用“throw”语句抛出异常类对象后,该对象必须马上被释放(析构)?
问题点数:20、回复次数:3Top
1 楼birdiez(溜达)回复于 2006-03-22 12:59:24 得分 15
1. MyException opps("Not positive",i); 是局部变量,throw 之后会被析构,因此需要复制一份到异常处理专用内存
2. catch 引用是正常用法。同函数调用一样,不是引用就是新的局部变量,因此去掉引用符号后多构造一个对象也正常
3. MyException 的 copy constructor 没有自定义,所以程序漏掉了两次构造没有输出
--------
unit--: 方便易用的 C++ 单元测试工具
http://unit--.sourceforge.net/
Top
2 楼howyougen(夫孝,德之本也,教之所由生也)回复于 2006-03-22 16:07:38 得分 5
“throw”语句抛出异常类对象后,该对象必须马上被释放(析构)?
抛出的异常对象(用copy ctor生成)不是马上释放
而是在最外面的catch退出时才会销毁
如把主程序改为:
int main(int argc, char *argv[])
{
int i;
try
{
try{
cout<<"Enter a positive number:";
cin>>i;
if (i<0) {
MyException opps("Not positive",i);
throw opps;
}
}
catch(MyException &e){
cout<<e.str_what<<": ";
cout<<e.what<<"\n";
throw; //
}
}
catch (...)
{
cout<<"exception is dtor\n"; //先输出这句,才输出This is ~MyException()
}
return 0;
}
Top
3 楼warsong(马小虎-郁闷中~~)回复于 2006-03-23 12:04:31 得分 0
接受答案了,谢谢大家!Top




