c++ - 我对 C++ catch 子句、异常类系列和销毁的使用是否正常?

标签 c++ exception-handling

偶尔,我会注意到一些我多年来一直使用的编码模式,这让我很紧张。我没有具体的问题,但我也不太记得我为什么采用该模式,而且它的某些方面似乎与某些反模式相匹配。这最近发生在我身上 WRT 我的一些代码如何使用异常。

令人担忧的事情涉及我“通过引用”捕获异常的情况,以类似于我处理函数参数的方式处理它。这样做的一个原因是我可以拥有异常类的继承层次结构,并根据应用程序指定更通用或更精确的捕获类型。例如,我可能会定义...

class widget_error {};
class widget_error_all_wibbly : public widget_error {};
class widget_error_all_wobbly : public widget_error {};

void wibbly_widget ()
{
  throw widget_error_all_wibbly ();
}

void wobbly_widget ()
{
  throw widget_error_all_wobbly ();
}

void call_unknown_widget (void (*p_widget) ())
{
  try
  {
    p_widget ();
  }
  catch (const widget_error &p_exception)
  {
    //  Catches either widget_error_all_wibbly or
    //  widget_error_all_wobbly, or a plain widget_error if that
    //  is ever thrown by anything.
  }
}

这让我很担心,因为我注意到类实例是在一个函数中构造的(作为抛出的一部分),但在该函数退出后被引用(通过 p_Exception catch 子句“参数”)。这通常是一种反模式——在函数内创建但在函数退出时传递出去的对局部变量或临时变量的引用或指针,通常是悬空引用/指针,因为局部变量/临时变量已被破坏并释放了内存当函数退出时。

一些快速测试表明上面的 throw 可能没问题——在 throw 子句中构造的实例在函数退出时不会被破坏,但在处理它的 catch 子句完成时被破坏——除非 catch block 重新抛出异常,在这种情况下,下一个 catch block 将完成这项工作。

我仍然感到紧张是因为在一个或两个编译器中运行的测试并不能证明标准所说的内容,而且根据我的经验,我认为常识通常与语言保证的内容不同。

那么 - 这种处理异常的模式(使用引用类型捕获它们)安全吗?或者我应该做其他事情,例如...

  • 捕获(并显式删除)指向堆分配实例的指针,而不是指向看起来(抛出时)非常像临时对象的对象的引用?
  • 使用智能指针类?
  • 使用“按值传递”catch 子句,并承认我无法使用一个 catch 子句从层次结构中捕获任何异常类?
  • 有什么我没想到的?

最佳答案

没关系。通过常量引用捕获异常实际上很好(捕获指针不好)。按值(value)捕获会创建不必要的拷贝。编译器足够聪明,可以正确处理异常(及其破坏)——只是不要尝试在 catch block 之外使用异常引用;-)

事实上,我经常做的是从std::runtime_error(继承自std::exception)继承我的层次结构。然后我可以使用 .what(),在处理更多异常的同时使用更少的 catch block 。

关于c++ - 我对 C++ catch 子句、异常类系列和销毁的使用是否正常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4552396/

相关文章:

exception-handling - Erlang 错误处理哲学 - case vs throw

c++ - C++ 中的全局数组

c++ - 指向 vector 的指针只返回 vector 的最后一个值

java - 不明确的@ExceptionHandler 方法映射

exception-handling - Swift Exceptions 异常处理

c++ - 编译时检测不应该抛出但仍然抛出的函数(noexcept 或替代方法)

c++ - 混合 C++ 异常处理和 SEH (windows)

c++ - 如何返回指向对象的指针以便在访问对象方法的函数中使用?

.net - Windows平台上不同类型的DLL

c++ - 创建一个指向包含字符串的新类的指针