繁体   English   中英

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

[英]How to Detect Stack Unwinding in a Destructor

我有一个简单的C ++对象,我在函数F()的开头创建,以确保在F()的启动和返回时调用两个匹配的函数(OpDo,OpUndo),方法是使用对象的构造函数和析构函数。 但是,如果在F()的主体内抛出异常,我不希望撤消操作。 这可以干净利落吗? 我读过有关std :: uncaught-exception的内容 ,但似乎并未建议使用它。

大多数人使用std::uncaught_exception()来尝试判断异常是否未决,因此如果没有析构函数,它们可以从析构函数中抛出异常。 这通常被认为不是一个好主意。

如果你想要在抛出异常时不撤消操作,它应该可以解决问题。

请记住,析构函数是释放对象所具有的任何资源的最后机会,因为在析构函数结束后,对象不存在,并且它所拥有的任何资源现在都会永久泄露。 如果OpDo()分配任何内存或文件句柄或其他什么,你需要在析构函数中处理它,无论如何。

你可以颠覆Scope Guard习语 相反的,当没有异常被抛出析构函数不能做的事情,我们认为反转且当不会引发任何异常做一些事情:

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上找到一个例子。

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

Helper F()
{
     MyClass doUndoWrapper;
}

当流量正常时 - 创建助手。 引发异常时,不会创建Helper的副本。 尝试通过放置到Helper的私有区域构造函数并将F声明为朋友来使用此语义 - 因此没有人可以创建帮助器。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM