删除者的呼叫上下文

时间:2015-03-15 12:03:09

标签: c++ smart-pointers

与标准智能指针一起使用的C ++ Deleter是否可以确定调用它的上下文?

让我们说释放我的资源可能会产生错误。

如果我的资源在堆栈展开期间被释放,我显然不希望我的Deleter在发生错误时抛出异常。但是如果使用reset()调用Deleter,那么向我的代码用户报告错误就可以了。

struct MyDeleter
{
  typedef ... pointer;

  void operator ()(pointer p)
  {
    if (release_p_failed)
    {
      if (throwing_exception_is_ok)
        throw ...;
      else
        hide_error_to_not_abort;
    }
  }
};

实施例

{
  std::unique_ptr<..., MyDeleter> p{ ..., MyDeleter };

  // A:
  p.reset(); // User intends to handle the error. Throwing exception is ok.

  // B: Leave scope and do not throw an exception in case of an error.
}

3 个答案:

答案 0 :(得分:1)

如果您担心在堆叠取消缠绕期间抛出异常,则应使用std::uncaught_exception,例如

struct MyDeleter
{
  typedef ... pointer;

  void operator ()(pointer p)
  {
    if (release_p_failed)
    {
      if (!std::uncaught_exception())   // no stack unwinding in progress
        throw ...;
      else
        hide_error_to_not_abort;
    }
  }
};

如果您需要从任何析构函数中抛出,这是使用的标准习惯用法。 当然,这无法区分从std::unique_ptr::~std::unique_ptrstd::unique_ptr::reset()被调用。

请注意,来自C ++ 17的std::uncaught_exception已被弃用并被std::uncaught_exceptions取代,并返回当前“空中”未捕获的例外数量。

答案 1 :(得分:0)

不,unique_ptr没有提供任何方法来确定删除器的调用上下文。

在这种情况下,您需要提供单独的清理逻辑。

答案 2 :(得分:0)

您可以使用std::uncaught_exception()来区分正常销毁和堆栈展开。