首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当抛出特定异常时,C++析构函数跳过工作的方法?

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

Stack Overflow用户
提问于 2010-07-24 07:35:15
回答 7查看 671关注 0票数 1

我在堆栈上有一个对象,我希望它的析构函数在调用析构函数时跳过一些工作,因为由于在堆栈上的对象的作用域中抛出了一个特定的异常,所以正在展开堆栈。

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

代码语言:javascript
运行
复制
RAII_Class pending;

try {
  doSomeWorkThatMayThrowException();
} catch (exceptionToSkipPendingDtor &err) {
  pending.notifySkipResourceRelease();
  throw;
}

然而,我希望有一种更优雅的方式来做这件事。例如,想象一下:

代码语言:javascript
运行
复制
RAII_Class::~RAII_Class {
  if (detectExceptionToSkipPendingDtorBeingThrown()) {
    return;
  }
  releaseResource();
}
EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2010-07-24 07:36:32

使用std::uncaught_exception()几乎可以做到这一点,但并不完全如此。

Herb Sutter比我更好地解释了“几乎”:http://www.gotw.ca/gotw/047.htm

在极少数情况下,当从析构函数调用时,std::uncaught_exception()返回true,但相关对象实际上并未被堆栈展开过程销毁。

没有RAII你可能会过得更好,因为它与你的用例不匹配。RAII的意思是总是清理,不管有没有异常。

你想要的要简单得多:只有在没有抛出异常的情况下才释放资源,这是一个简单的函数序列。

代码语言:javascript
运行
复制
explicitAllocateResource();
doSomeWorkThatMayThrowException();
explicitReleaseResource(); // skipped if an exception is thrown
                           // by the previous function.
票数 8
EN

Stack Overflow用户

发布于 2010-07-24 07:38:51

我会以另一种方式来做-明确地告诉它如果没有抛出异常就去做它的工作:

代码语言:javascript
运行
复制
RAII_Class pending;

doSomeWorkThatMayThrowException();

pending.commit(); // do or prepare actual work
票数 5
EN

Stack Overflow用户

发布于 2010-07-24 07:51:44

这似乎绕过了使用RAII的主要原因。RAII的要点是,如果在代码中途发生异常,您仍然可以正确地释放资源/被析构。

如果这不是你想要的语义,那么不要使用RAII。

因此,不是:

代码语言:javascript
运行
复制
void myFunction() {
    WrapperClass wc(acquireResource());

    // code that may throw
}

只需这样做:

代码语言:javascript
运行
复制
void myFunction() {
    Resource r = acquireResource();

    // code that may throw

    freeResource(r);
}

如果中间的代码抛出,资源将不会被释放。这就是您想要的,而不是保留RAII (并保留名称),而不是实现RAII语义。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3323102

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档