C++ catch块 - 按值或引用捕获异常?

Mr.*_*Boy 92 c++ exception-handling

可能重复:
在C++中通过指针捕获异常

我总是通过价值来捕捉异常.例如

try{
...
}
catch(CustomException e){
...
}
Run Code Online (Sandbox Code Playgroud)

但我遇到了一些相反的代码catch(CustomException &e).这是a)罚款b)错误c)灰色区域?

Jar*_*Par 136

C++中异常的标准做法是......

按价值投掷,以参考方式捕获

面对继承层次结构,按值获取是有问题的.假设您的示例存在另一种类型MyException,它继承CustomException并覆盖错误代码之类的项目.如果MyException抛出了一个类型,你的catch块会导致它被转换为一个CustomException导致错误代码改变的实例.

  • @Danial Earwicker:为什么你可以通过非const引用捕获它"不幸"?异常对象总是被复制,所以无论你抛出什么"对象",你都不能影响任何catch块的原始对象,因为抛出的'object'实际上只是一个初始化器.const没有被丢弃; 异常对象总是非常量,非易失性.允许通过非const引用捕获使中间catch块可以向异常添加信息.它并不常用,但如果你需要的话它就在那里. (25认同)
  • 对此我要补充:通过const引用捕获.不幸的是,您可以抛出一个const对象并使用非const引用捕获它.为了避免const的这种无声"抛弃",总是捕获一个const引用,并确保你的异常类型具有const-correct访问器. (7认同)
  • @Daniel:澄清Charles(并发送到你的收件箱),你可以捕获和重新抛出的异常对象是一个临时的定义.`throw`的参数应该在堆栈中,并且应该作为展开的第一个业务顺序销毁.`throw new`是一个错误. (5认同)
  • @Charles - 你是对的,它并没有真正丢掉const.我想我用与非const引用传递给方法的临时相同的术语来考虑它,在该语言的其他地方禁止该方法以避免尝试通过引用变异临时(当突变将被丢弃时)无论如何).但正如你所说,你可能想故意改变异常然后`throw;`这使得它在其他地方可见(因此打破了我的类比). (3认同)
  • @John:第15章异常,特别是15.3(异常处理)描述了如何从异常对象初始化catch参数.如果参数是类类型(而不是引用),则通过复制构造函数初始化它. (2认同)

CB *_*ley 27

如果异常属于您捕获的类型的派生类型,则按值捕获将切片异常对象.

这对于catch块中的逻辑可能有问题,也可能无关紧要,但没有理由不通过const引用捕获.

请注意,如果throw;在catch块中没有参数,则无论是否捕获到切片副本或对异常对象的引用,都会重新引发原始异常.

  • 我认为"切片"是一个术语,用于参考传递语言的人喜欢使用.如果你将一个派生对象分配给它的基类型,你的想法就是"切掉"对象的一部分,这对我来说似乎是一种误导性的方式来看待它,因为实际发生的是基类的复制赋值运算符base&operator =(const base&other)`派生对象被隐式转换为`base&`引用,因此赋值将派生类视为与基类相同.没有神奇的切片或转移东西,你正在调用一个函数 (10认同)
  • 在这种情况下,我不熟悉*slice*这个术语. (8认同)

Mar*_*tos 9

除非您想要处理异常,否则通常应该使用const引用:catch (const CustomException& e) { ... }.编译器处理抛出对象的生命周期.