Possible Duplicate:
Can a local variable’s memory be accessed outside its scope?
代码:
#include <iostream>
using namespace std;
class B{
public:
int b;
B():b(1){}
~B(){cout << "Destructor ~B() " << endl;}
};
class A{
public:
B ob;
A()try{throw 4;}
catch(...){cout << "Catched in A() handler : ob.b= " << ob.b<<endl;}
};
int main()try{
A t;
}
catch(...){cout << "CATCHED in Main" << endl;}
输出:
Destructor ~B()
Catched in A() handler : ob.b= 1
CATCHED in Main
我的问题是如何访问其析构函数调用已完成的对象 ob
的成员变量 b
。
使用被破坏的对象是未定义的行为。这意味着您现在可能会出现这种行为,但无法保证您会在其他时间出现这种情况。未定义的行为比常规错误更危险,因为它更难检测,如本例所示。
更新:在一些评论之后,我将解释为什么 OP 的代码会产生该输出。
try
功能 block 在 C++ 中是一个有点晦涩的功能。您可以将函数的整个主体包围在 try
block 中,并使用相应的 catch
。这是,而不是:
void foo()
{
try
{
//...
}
catch (/*whatever*/)
{
//...
}
}
你可以这样写:
void foo()
try
{
//...
}
catch (/*whatever*/)
{
//...
}
这实际上不是很有用,但对于构造函数可能有点用处,因为这是将初始化列表包含在 try
block 中的唯一方法。因此,OP 的 A
构造函数代码等同于:
A()
try
: b()
{
throw 4;
}
catch(...)
{
cout << "Catched in A() handler : ob.b= " << ob.b<<endl;
}
我说过这只是有点用处,因为您不能使用您在 catch
block 中构建的对象;如果你在 try
block 中抛出异常,异常将离开构造函数主体,因此该对象将永远不会被构造,并且任何构造的数据成员将在进入 catch
之前立即被销毁> 阻止。但它可能对日志记录有一定的用处。
现在,众所周知,构造函数(假设我们没有使用 nothrow
版本)只能做两件事:
- 返回一个构造好的对象
- 抛出异常
在这个构造函数中我们抛出异常,但是异常在 catch
block 中被捕获。那么现在发生了什么?调用构造函数的代码将返回什么?我们不能返回构造对象,因为我们没有,所以只有一个选择:catch
block 必须抛出。在这种情况下,这实际上是标准要求的。如果我们没有显式抛出,编译器会在 catch
block 的末尾默默地添加一条 throw;
指令。因此,详细说明一下,构造函数等同于以下内容:
A()
try
: b()
{
throw 4;
}
catch(...)
{
cout << "Catched in A() handler : ob.b= " << ob.b<<endl;
throw;
}
这就是异常被捕获两次的原因:一次在 A
构造函数中,一次在 main()
中。