C++ RAII析构函数异常

标签 c++ exception destructor raii

据我理解RAII指的是在ctor中获取资源,在dtor中释放。

Ctor 获取一些资源可能会失败,导致异常。 Dtor 释放资源,也可能失败,但 dtors 的异常是 foobar,所以也不异常(exception)。

class A {
  A() throw(Ex) { // acquire resources }
  ~A() throw() { // release resources }
}

因此,如果 A 类的用户应该知道 A 的未初始化中发生错误,我可以将未初始化外包给一个抛出的函数,从吞噬异常的 dtor 调用:

class A {
  A() throw(Ex) { // acquire resources }
  ~A() throw() { try {Release(); } catch(...) {} }

  void Release() throw(Ex) { // release resources }
}

这样,如果用户想要发布错误的反馈,或者只是在 A 超出范围时让 dtor 执行它的工作而忽略(例如,在使用 A 的地方发生其他一些异常),则用户可以调用 Exit()。

为了防止 Exit() 的多次执行(首先由用户显式执行,后来由 dtor 间接执行),我必须添加一个初始化状态:

class A {
  bool init;
  A() throw(Ex) { init = true; // acquire resources }
  ~A() throw() { try {Release(); } catch(...) {} }

  void Release() throw(Ex) {
    if(!init) return;
    init = false;
    // release resources
   }
}

是否有更好的方法来做到这一点,或者我是否必须在每次资源释放失败并且我想了解它时实现该模式?

最佳答案

释放资源不应该有任何失败的范围。比如释放内存当然可以用不抛出异常的形式来实现。 RAII 旨在清理资源,而不是处理大量清理导致的错误。

显然,有些清理操作可能会失败。例如,关闭文件可能会失败,例如,因为关闭它会刷新内部缓冲区,并且可能会因为文件正在写入的磁盘已满而失败。如果清理操作失败,可能应该有一个合适的释放操作,如果用户有兴趣报告清理中的错误,他们应该使用这种方法:在正常路径中,将有机会处理任何错误.

当释放作为处理现有错误的一部分时,即抛出异常并且未达到释放操作时,析构函数需要吃掉任何异常。可能有一些处理方法,例如,记录抛出异常的消息,但异常不应逃脱析构函数。

关于C++ RAII析构函数异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23721914/

相关文章:

c++ - 仔细检查我的知识 : Unicode

c++ - 如果一个函数没有返回值,但返回类型有效,编译器是否可以返回垃圾?

c++ - 平凡可移动但不可平凡复制

parsing - XAML解析异常

c++ - 在八叉树数组上调用删除

c++ - 析构函数可以递归吗?

c++ - 如果我将一个基类的析构函数从非虚拟更改为虚拟,会发生什么?

c++ - QtRPT 连接错误,没有匹配函数调用到 reportWindow::connect

c++ - c++ 中深层嵌套函数的单个 catch all 语句?

java.lang.NumberFormatException : For input string: "22"