首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何检测析构函数中的堆栈展开

如何检测析构函数中的堆栈展开
EN

Stack Overflow用户
提问于 2010-10-25 20:24:54
回答 3查看 1.3K关注 0票数 7

我在函数F()的开头创建了一个简单的C++对象,通过使用对象的构造函数和析构函数,确保在F()的开始和返回时调用两个匹配的函数(OpDo和OpUndo)。但是,我不希望在F()的主体中抛出异常时撤消该操作。这能干净利落吗?我读过关于std::uncaught-exception,的文章,但似乎不推荐使用它。

EN

回答 3

Stack Overflow用户

发布于 2010-10-25 20:31:37

大多数人都使用std::uncaught_exception()来判断异常是否挂起,所以如果还没有异常,他们就可以从析构函数中抛出异常。这通常被认为不是一个好主意。

如果您不想撤销一个异常抛出的操作,那么它应该可以做到这一点。

请记住,析构函数是释放对象所拥有的任何资源的最后一次机会,因为在析构函数结束后,对象不存在,它所持有的任何资源现在都会永久泄漏。如果OpDo()分配了任何内存或文件句柄或其他任何东西,那么无论如何都需要在析构函数中处理这些问题。

票数 6
EN

Stack Overflow用户

发布于 2011-04-17 08:08:49

你可以颠覆范围保护成语。当不抛出异常时,不执行在析构函数中执行的操作,相反,如果没有抛出异常,则只执行操作:

代码语言:javascript
复制
class DoUndoRAII{
public:
  DoUndoRAII()
    : noexcept_(false)
  {
    // your stuff here
  }

  ~DoUndoRAII(){
    if(noexcept_){
      // do whatever you need to do
    }
  }

  void no_exception(){
    noexcept_ = true;
  }

private:
  bool noexcept_;
};

void func(){
  DoUndoRAII do_undo;

  // last line
  do_undo.no_exception();
}

当抛出异常时,do_undo.no_exception()将不会被调用,因此也不会将noexcept_值设置为true。)一个例子可以找到在Ideone

票数 1
EN

Stack Overflow用户

发布于 2010-10-25 20:40:23

让我们假设您的F返回一些类Helper:

代码语言:javascript
复制
Helper F()
{
     MyClass doUndoWrapper;
}

当流正常时,创建帮助程序。当引发异常时,将不创建Helper的副本。尝试使用此语义,将其放置到helper的私有区域构造函数中,并声明F为friend,这样就没有人可以创建助手。

代码语言:javascript
复制
class Helper
{
private:
    friend Helper F();
    Helper(){ //place there OpDo semantic - first entry 
              // construct this class
    Helper(const Helper& copy){ //this must present to allow stack operations
              // copy constructor will be called at end of `F` to return value
              // so place OpUndo semantic there to mark success without exception
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4018553

复制
相关文章

相似问题

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