通过引用捕获异常时未创建临时对象?

时间:2012-07-07 05:50:28

标签: c++ visual-c++ exception exception-handling

class Error1
{

public:

int errorcode;
Error1(int x):errorcode(x){ cout<<"CTOR Error1"<<endl; }
//Error1(Error1& obj ){
//    errorcode = obj.errorcode;
//    cout<<"CopyCTOR Error1"<<endl;
//}
~Error1(){cout<<"DTOR Error1"<<endl; }
};

void fun()
{
cout<<"Inside fun"<<endl;
throw(Error1(5));
}

int main()
{
try{

    fun();
}
catch(Error1& eobj)
{
    cout<<"Error1 type occured with code:"<<eobj.errorcode<<endl;
}
cin.get();

}

输出:

Inside fun

CTOR Error1

DTOR Error1

Error1 type occured with code:5

DTOR Error1

此输出表明Error1对象是为catch处理程序构造的副本。由于未为Error1对象定义复制构造函数,因此使用默认复制构造函数。

当我取消注释用于定义复制构造函数的注释部分时,我得到以下输出。

Inside fun

CTOR Error1

Error1 type occured with code:5

DTOR Error1

为什么只有一个DTOR被调用?即使通过引用捕获异常,我相信仍然会创建临时。

2 个答案:

答案 0 :(得分:1)

您使用的是哪种编译器?

当您使用Error1& obj参数引入(即取消注释)您的版本的复制构造函数时,代码应该变为无效。 throw应该能够创建其参数的副本,而您的版本的复制构造函数禁用临时复制。代码格式不正确。如果您的编译器接受它,可能是因为它非法允许绑定非临时引用到temporaries(我怀疑它是MSVC ++编译器并启用了扩展)。

原始实验按照假设/允许的方式工作。 throw的参数被复制到内部临时,后来用于初始化catch参数。虽然允许编译器直接使用原始临时文件,但相应地延长其生命周期。

答案 1 :(得分:-1)

可能还有其他错误,但我现在看到的是throw(Error1(5));创建了rvalue类型的临时(或Error1)。你想要一个lvalue,这意味着你应该做throw(*new Error1(5));(我认为会造成内存泄漏,但我可能错了),或者你可以创建一个全局Error1对象然后抛出那个。

PS:我很想知道throw(*new Error1(5));是否会造成内存泄漏,如果有人愿意发表评论。 catch会破坏它捕获的对象吗?如果是这样的话,我认为只要你需要它就可以创建新的Error1