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

Is it safe to use an exception outside the catch statement if it is held in a std::exception_ptr?

我有一个 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;

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

Is it safe to use an exception outside the catch statement if it is held in a std::exception_ptr?

是的。您可以将 exception_ptr 视为指向异常的引用计数指针。只要 exception_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';
    }
}

在 gcc 和 clang 上输出:

other text

这表明 aePtr 指的是完全相同的对象。

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

some text

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

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

在我看来,rethrow_exception 在 VS 上进行了复制,这意味着原始问题中 e 的生命周期不能保证与 ePtr 相关联。