引用在try catch中没有按预期工作

时间:2012-03-22 12:44:22

标签: c++

#include <iostream>
using namespace std;

int main (int argc, char* const argv[]) {
    int a = 20;
    cout<<"address of a is "<<&a<<endl;
    try{
        throw a;
    }
    catch (int& z) {
            cout<<"address of z is "<<&z<<endl;
    }
    return 0;
}

a的地址与z的地址不同。这意味着引用在try catch中不起作用。如果没有那么为什么编译器不会产生任何错误?以上代码意味着什么?

2 个答案:

答案 0 :(得分:3)

当您抛出任何类型的对象时,标准允许编译器根据需要多次复制对象。因此,在catch块中,您可能无法获得您投掷的原始对象,而是它可以是另一个对象,它是原始对象的副本,或者是原始对象副本的副本,或者等等。

答案 1 :(得分:2)

我想我的评论不太清楚,所以我写了一些答案。

当您抛出该异常时,您将其按值抛出。这意味着它将被复制(如果它是原始类型或复制对象则无关紧要)。当然,当复制一个对象时,它的内存位置会发生变化(它是一个 new 对象)。为什么这个?因为异常可以展开堆栈以找到正确的catch块。如果你通过引用扔东西你可能得到的是垃圾(因为当变量超出范围时它将被销毁)。我说可能因为实际上编译器不允许抛出引用而你总是有副本。

如果您的异常对象非常大,您可以考虑使用new分配对象,然后抛出其指针。但某人必须解除分配。你准备好冒风险了吗?看一下(例如)MFC上的CException实现及其Delete()方法(他们试图让这很简单,但我对此并不高兴)。

也许你想知道为什么如果你必须通过引用抓住你的价值。首先是因为它是std::exception的设计方式(尝试通过值调用>的what()方法。其次,因为它允许编译器执行某些优化(此外,即使您不使用std :: exception,也不会创建该对象的无用副本)。