一道有趣的题目

来源:互联网 发布:安川伺服驱动器编程 编辑:程序博客网 时间:2024/04/28 15:28

今天在群里有人问了一个有趣的问题。

#include <conio.h>
#include <iostream>
using namespace std;

// 只要有e诞生或死亡,就输出个东西来
class e
{
public:
e(void){ cout<<"default constructor"<<endl;}
e(const e& e1){ cout<<"copy constructor"<<endl;}
e& operator=(const e& e1){ cout<<"assignment"<<endl;}
~e(void){ out<<"destructor"<<endl;}
};

// 扔出一个异常
void fun(void){       throw(0);}

// 调用一个会扔出异常的函数
void fun_e1(e e1){ fun();}

// 通过溢出产生一个异常出来
void fun_e2(e e2){ int i; i /= (i = 0);}

// 手工抛出一个异常
void fun_e3(e e3){  throw(0);}

int _tmain(int argc, _TCHAR* argv[])
{
 e e1;

 try
 {
  fun_e1(e1);
 }
 catch(...)
 {
 }

 return 0;
}

class view
{
public:
view(void)
{ cout<<"-oh my god"<<endl;}

~view(void)
{
     cout<<"-can u see"<<endl;
     while(!kbhit());
}
}v;


// 一个Object如果被完美创建,那么在离开它的scope时,会被destructor
// 在try中,调用fun_e1, 得到输出
-oh my god
default constructor
copy constructor
destructor
destructor
-can u see

// 在try中,调用fun_e2,得到输出
-oh my god
default constructor
copy constructor
destructor
-can u see

// 在try中,调用fun_e3,得到输出
-oh my god
default constructor
copy constructor
destructor
destructor
-can u see

// 注意调用fun_e2,即不是显式throw一个异常的时候
// 我们得到(至少是在输出上)两个构造和一个析构,这少
// 掉的一个析构跑到哪里去了?

两次调用差别在于一次是Throw,一次是除零溢出。为什么除零溢出导致少了一次析构呢?昨天刚刚看了
异常处理,所以分析是因为对象是临时变量,i也是临时变量,i溢出导致复写了e,似乎很有道理,但是认真
想了一下,不对,i /= (i = 0); 应该是
xor eax,eax
idiv eax,eax
mov [esp-4],eax
应该在 idiv eax,eax这一步就出错了,还没到堆栈呀。

那么到底是什么原因呢?

原创粉丝点击