如何保存异常并稍后抛出

Edw*_*alk 3 c++ exception

假设我想创建一个异常对象,但稍后再抛出它。我的用例是异常是在线程中生成的,但我需要实际从主线程中抛出它(因为没有人在子线程中捕获它)

using namespace std;

runtime_error *ex = nullptr;

thread myThread( [&ex]{
    if (something_went_wrong) {
        ex = new runtime_error("Something went wrong");
        return;
    }
} );

myThread.join();
if (ex != nullptr) {
    throw *ex;
}
Run Code Online (Sandbox Code Playgroud)

就其价值而言,编译器似乎对此感到满意,但我可以看到这充其量只是资源泄漏。有正确的方法吗?

Art*_*yer 5

std::exception_ptr是 C++ 存储异常的工具。它通常可以避免额外的分配。

std::exception_ptr ex = nullptr;

std::thread myThread( [&ex]{
    if (something_went_wrong) {
        ex = std::make_exception_ptr(std::runtime_error("Something went wrong"));
        return;
    }
} );

myThread.join();
if (ex != nullptr) {
    std::rethrow_exception(ex);
}
Run Code Online (Sandbox Code Playgroud)

由于它可以存储任何类型的异常,因此您可以通过包装 lambda 来存储可能在线程中抛出的任何内容,如下所示:

std::thread myThread( [&ex]{
    try {
        // do things
    } catch (...) {
        ex = std::current_exception();
    }
} );
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用std::optional<std::runtime_error>

std::optional<std::runtime_error> ex;

std::thread myThread( [&ex]{
    if (something_went_wrong) {
        ex.emplace("Something went wrong");
        return;
    }
} );

myThread.join();
if (ex) {
    throw *ex;
}
Run Code Online (Sandbox Code Playgroud)

由于您不动态分配,因此不会泄漏