C++析构函数在抛出特定异常时跳过工作的方法?

Wil*_*mKF 1 c++ destructor exception raii

我在堆栈上有一个对象,我希望它的析构函数在调用析构函数时跳过一些工作,因为堆栈正在解开,因为特定的异常是通过堆栈上的对象范围抛出的.

现在我可以在堆栈项的范围内添加一个try catch块并捕获有问题的异常并通知堆栈对象不运行要跳过的工作然后重新抛出异常,如下所示:

RAII_Class pending;

try {
  doSomeWorkThatMayThrowException();
} catch (exceptionToSkipPendingDtor &err) {
  pending.notifySkipResourceRelease();
  throw;
}
Run Code Online (Sandbox Code Playgroud)

但是,我希望有更优雅的方式来做到这一点.例如想象:

RAII_Class::~RAII_Class {
  if (detectExceptionToSkipPendingDtorBeingThrown()) {
    return;
  }
  releaseResource();
}
Run Code Online (Sandbox Code Playgroud)

CB *_*ley 8

你几乎可以做到这一点std::uncaught_exception(),但并不完全.

Herb Sutter解释说"几乎"比我做得更好:http://www.gotw.ca/gotw/047.htm

有一些极端情况,std::uncaught_exception()当从析构函数调用时返回true,但有问题的对象实际上并未被堆栈展开过程销毁.

没有RAII你可能会更好,因为它与你的用例不符.RAII意味着总是清理; 是否例外.

你想要的更简单:只有在没有抛出异常时才释放资源,这是一个简单的函数序列.

explicitAllocateResource();
doSomeWorkThatMayThrowException();
explicitReleaseResource(); // skipped if an exception is thrown
                           // by the previous function.
Run Code Online (Sandbox Code Playgroud)


Geo*_*che 5

我会反过来做 - 如果没有抛出异常,明确告诉它做它的工作:

RAII_Class pending;

doSomeWorkThatMayThrowException();

pending.commit(); // do or prepare actual work
Run Code Online (Sandbox Code Playgroud)