std::uncaught_exception, std::uncaught_exceptions

来自cppreference.com
< cpp‎ | error
在标头 <exception> 定义
(1)
bool uncaught_exception() throw();
(C++11 前)
bool uncaught_exception() noexcept;
(C++11 起)
(C++17 中弃用)
(C++20 中移除)
int uncaught_exceptions() noexcept;
(2) (C++17 起)
1) 检测当前线程是否有生存的异常对象,即被抛出或重抛出且未进入匹配的 catch 子句、std::terminatestd::unexpected 的异常。换言之,std::uncaught_exception 检测当前是否在进行栈回溯
2) 检测当前线程已经抛出或重抛出且未进入其匹配 catch 子句的异常对象数。

有时抛出异常是安全的,即使当 std::uncaught_exception() == true。例如,如果栈回溯导致要析构对象,那么该对象的析构函数可以运行抛出异常的代码,只要在离开析构函数前为某 catch 块捕获该异常。

参数

(无)

返回值

1) 此线程中当前正在进行栈回溯时返回 true,否则返回 false
2) 当前线程中未捕获的异常对象的数量。

注解

返回 int 的 uncaught_exceptions 的一个使用例子是 boost.log 库:表达式 BOOST_LOG(logger) << foo(); 首先创建保障对象并记录其构造函数中的未捕捉异常数。由保障对象的析构函数进行输出,除非 foo() 抛出。(此时析构函数中未捕获的异常的数量大于构造函数所观察到的)

LFTS v3 中的 std::experimental::scope_failstd::experimental::scope_success 依赖 uncaught_exceptions 的功能,因为它们需要取决于析构函数是否在栈回溯中调用而做不同的事。

功能特性测试
__cpp_lib_uncaught_exceptions

示例

#include <iostream>
#include <exception>
#include <stdexcept>
 
struct Foo
{
    int count = std::uncaught_exceptions();
 
    ~Foo()
    {
        std::cout << (count == std::uncaught_exceptions()
            ? "正常调用 ~Foo()\n"
            : "在栈回溯中调用 ~Foo()\n");
    }
};
 
int main()
{
    Foo f;
 
    try
    {
        Foo f;
        std::cout << "抛出异常\n";
        throw std::runtime_error("测试异常");
    }
    catch (const std::exception& e)
    {
        std::cout << "捕获到异常:" << e.what() << '\n';
    }
}

输出:

抛出异常
在栈回溯中调用 ~Foo()
捕获到异常:测试异常
正常调用 ~Foo()

缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 出版时的行为 正确行为
LWG 70 C++98 uncaught_exception() 的异常说明缺失 补充说明 throw()

参阅

异常处理失败时调用的函数
(函数)
用于处理异常对象的共享指针类型
(typedef)
捕获当前异常到 std::exception_ptr 之中
(函数)

外部链接