关于 RAII,C++“尝试”/“捕获”块是否与其他块相同

Are C++ `try`/`catch` blocks the same as other blocks, regarding RAII?

本文关键字:是否 其他 RAII C++ 尝试 关于 捕获      更新时间:2023-10-16

好的,那么如果我使用 RAII 习语来管理某些上下文属性*,如果我在 try 块的开头裸露地使用它,它会按我预期的那样工作吗?

换句话说,如果我有这个:

struct raii {
    raii() {
        std::cout << "Scope init"
                  << std::endl; }
    ~raii() {
        std::cout << "Scope exit"
                  << std::endl; }
};

。我成功地像这样使用它:

{
    raii do_the_raii_thing;
    stuff_expecting_raii_context();
    /* … */
}

。如果我这样做,RAII 实例的工作方式是否相同:

try {
    raii do_the_raii_thing;
    stuff_expecting_raii_context_that_might_throw();
    /* … */
} catch (std::exception const&) {
    /* … */
}

这可能是一个愚蠢的问题,但我想检查一下我自己的理智——我对noexcept保证和其他与异常相关的细节的微妙之处很模糊——所以请原谅我的天真


[*] 对于那些好奇的人来说,在我的特定情况下,我正在使用 RAII 管理的 Python C-API 的邪恶 GIL(全局解释器锁)。

是的,它将完全按照您的要求执行:首先释放 RAII 资源,然后处理异常块。

"...如果我这样做,RAII 实例的工作方式是否相同:..."

当然会。如果抛出异常,RAII 实例将超出范围,析构函数将在catch之前调用。

这也适用于任何更高的级别,如果您只是throw并且没有任何try/catch块,则会调用您的函数。这就是所谓的堆栈展开

是的

,这是在标准中指定的:

15.2 构造函数和析构函数 [除外]

2 为每个类类型的自动对象调用析构函数 自进入try块以来建造。自动对象 以与其完成相反的顺序销毁 建设。

相关文章: