与标准智能指针一起使用的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.
}
答案 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_ptr
和std::unique_ptr::reset()
被调用。
请注意,来自C ++ 17的std::uncaught_exception
已被弃用并被std::uncaught_exceptions
取代,并返回当前“空中”未捕获的例外数量。
答案 1 :(得分:0)
不,unique_ptr
没有提供任何方法来确定删除器的调用上下文。
在这种情况下,您需要提供单独的清理逻辑。
答案 2 :(得分:0)
您可以使用std::uncaught_exception()
来区分正常销毁和堆栈展开。