我在堆栈上有一个对象,我希望它的析构函数在调用析构函数时跳过一些工作,因为由于在堆栈上的对象的作用域中抛出了一个特定的异常,所以正在展开堆栈。
现在,我可以在stack项的作用域中添加try catch块,捕获有问题的异常,并通知stack对象不要运行要跳过的工作,然后重新抛出异常,如下所示:
RAII_Class pending;
try {
doSomeWorkThatMayThrowException();
} catch (exceptionToSkipPendingDtor &err) {
pending.notifySkipResourceRelease();
throw;
}然而,我希望有一种更优雅的方式来做这件事。例如,想象一下:
RAII_Class::~RAII_Class {
if (detectExceptionToSkipPendingDtorBeingThrown()) {
return;
}
releaseResource();
}发布于 2010-07-24 07:36:32
使用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.发布于 2010-07-24 07:38:51
我会以另一种方式来做-明确地告诉它如果没有抛出异常就去做它的工作:
RAII_Class pending;
doSomeWorkThatMayThrowException();
pending.commit(); // do or prepare actual work发布于 2010-07-24 07:51:44
这似乎绕过了使用RAII的主要原因。RAII的要点是,如果在代码中途发生异常,您仍然可以正确地释放资源/被析构。
如果这不是你想要的语义,那么不要使用RAII。
因此,不是:
void myFunction() {
WrapperClass wc(acquireResource());
// code that may throw
}只需这样做:
void myFunction() {
Resource r = acquireResource();
// code that may throw
freeResource(r);
}如果中间的代码抛出,资源将不会被释放。这就是您想要的,而不是保留RAII (并保留名称),而不是实现RAII语义。
https://stackoverflow.com/questions/3323102
复制相似问题