当你抛出 ex 时,它被复制到用于抛出异常对象的特殊内存位置。这种复制是由普通的复制构造函数执行的。
你可以从这个例子中很容易地看到这一点:
#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;
}
样本输出:
matteo@teolapubuntu:~/cpp/test$ g++ -O3 -Wall -Wextra -ansi -pedantic ExceptionStack.cpp -o ExceptionStack.x
matteo@teolapubuntu:~/cpp/test$ ./ExceptionStack.x
0xbf8e202f - inside default constructor
0x9ec0068 - inside copy constructor
0xbf8e202f - inside destructor
Caught exception (0x9ec0068)
0x9ec0068 - inside destructor
顺便说一句,您可以在这里看到,用于抛出对象的内存位置 (0x09ec0068) 肯定远离原始对象之一 (0xbf8e202f):堆栈和往常一样具有高地址,而用于抛出的对象在虚拟地址空间中相当低。尽管如此,这是一个实现细节,因为正如其他答案所指出的那样,标准并没有说明抛出对象的内存应该在哪里以及应该如何分配。