【问题标题】:C++ catch blocks - catch exception by value or reference? [duplicate]C++ catch 块 - 通过值或引用捕获异常? [复制]
【发布时间】:2011-02-01 02:42:13
【问题描述】:

可能重复:
catch exception by pointer in C++

我总是按值捕获异常。例如

try{
...
}
catch(CustomException e){
...
}

但我遇到了一些代码,它改为 catch(CustomException &e)。这是 a) 好的 b) 错误的 c) 灰色区域吗?

【问题讨论】:

  • 请注意,正确的引用也是常量:catch(CustomException const &e)...
  • 不应被标记为重复——通过 ptr 捕获异常与通过引用或值捕获不同。

标签: c++ exception-handling


【解决方案1】:

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

这对你的 catch 块中的逻辑可能很重要,也可能无关紧要,但没有什么理由不通过 const 引用来捕捉。

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

【讨论】:

  • 我不熟悉这个上下文中的术语slice
  • 我认为“切片”是习惯于引用传递语言的人喜欢使用的术语。这个想法是,如果您将派生对象分配给其基类型,则您“切掉”对象的一部分,在我看来,这似乎是一种误导性的看待它的方式,因为实际发生的是在基类的复制赋值运算符 @ 987654322@ 派生对象被隐式转换为base & 引用,因此赋值将派生类视为与基类相同。没有神奇的切片或传输东西,你正在调用一个函数
  • @Injektilo 我认为这里的slice主要关注虚函数。您使用基类引用来捕获派生类异常对象,因此动态绑定在这里很有用。对于按值捕获,基类对象丢失派生类详细信息,对于按引用捕获,派生类信息只是隐藏。
【解决方案2】:

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

按值抛出,按引用捕获

在继承层次结构面前,按值捕获是有问题的。假设您的示例有另一种类型 MyException 继承自 CustomException 并覆盖错误代码等项目。如果抛出 MyException 类型,您的 catch 块将导致它转换为 CustomException 实例,这将导致错误代码发生更改。

【讨论】:

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

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

【讨论】:

    【解决方案4】:

    (CustomException e) 中创建了 CustomException 的新对象...因此将调用它的构造函数,而在 (CustomException &e) 中它将只是引用...没有创建新对象并且不会调用构造函数...所以正式有点开销......以后更好用......

    【讨论】:

    • 在参考场景中,e的内存是如何释放的?如果e在栈中,catch块就变得没有意义了?
    猜你喜欢
    • 2012-06-04
    • 2011-10-06
    • 2015-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-05
    • 2016-06-26
    相关资源
    最近更新 更多