如果它保存在std :: exception_ptr中,在catch语句之外使用异常是否安全?

And*_*uel 5 c++ exception-handling exception c++11

std::exception_ptr内心有一个例外.我将调用std::rethrow_exception以获取实际异常,异常在catch语句之后是否有效?我的猜测是,因为我仍然坚持std::exception_ptr它仍然有效.

看例子:

std::exception_ptr ePtr = initialize_somewhere_else();
std::runtime_error* a=NULL;
try {
    std::rethrow_exception(ePtr);
} catch(std::runtime_error& e) {
    a = &e;
}
std::cout << a << ", " << a->what() << std::endl;
Run Code Online (Sandbox Code Playgroud)

注意:在我使用Clang的测试中,这确实有效.

How*_*ant 3

如果异常保存在 std::exception_ptr 中,那么在 catch 语句之外使用异常是否安全?

是的。您可以将其视为exception_ptr指向异常的引用计数指针。只要 anexception_ptr引用了该异常,该异常就会一直存在,并且不再存在。

此外,rethrow_exception不复印。

抱歉,我想我给出了错误的答案。

这是一个检测测试:

#include <iostream>
#include <exception>
#include <stdexcept>


int
main()
{
    auto ePtr = std::make_exception_ptr(std::runtime_error("some text"));
    std::runtime_error* a = nullptr;
    try
    {
        std::rethrow_exception(ePtr);
    }
    catch(std::runtime_error& e)
    {
        a = &e;
    }
    *a = std::runtime_error("other text");
    try
    {
        std::rethrow_exception(ePtr);
    }
    catch(const std::runtime_error& e)
    {
        std::cout << e.what() << '\n';
    }
}
Run Code Online (Sandbox Code Playgroud)

在 gcc 和 clang 上,输出:

other text
Run Code Online (Sandbox Code Playgroud)

这表明aePtr引用完全相同的对象。

然而,VS,根据http://webcompiler.cloudapp.net输出的当前版本:

some text
Run Code Online (Sandbox Code Playgroud)

这表明aePtr指的是不同的对象。

现在的问题是VS在这方面是否符合。我的意见是,这并不重要。这是该标准的一个有争议的领域,如果有争议,该标准将被更改以符合现有实践。

在我看来,rethrow_exception在 VS 上复制了一个副本,这意味着e原始问题中的生命周期不能保证与ePtr.