关于 RAII,C++ `try`/`catch` 块是否与其他块相同?

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

好的,如果我使用 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资源,再处理异常块。

"… will the RAII instance work the same way if I do this: ..."

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

这也适用于任何更高级别,如果您只是 throw 并且没有任何 try/catch 块,则调用您的函数。那叫stack unwinding.

是的,这是在Standard中指定的:

15.2 Constructors and destructors [except.ctor]

2 The destructor is invoked for each automatic object of class type constructed since the try block was entered. The automatic objects are destroyed in the reverse order of the completion of their construction.