标准库抛出哪些异常 std exception类体系分析

c++++标准库中的异常体系以std::exception为核心基类,所有标准异常均派生自它,用于构建健壮的异常处理机制。1. std::exception定义在头文件中,提供虚函数what()返回异常描述信息。2. 逻辑错误如std::logic_error及其子类std::domain_error、std::invalid_argument、std::length_error、std::out_of_range和std::future_error,表示程序可检测的逻辑问题。3. 运行时错误如std::runtime_error及其子类std::range_error、std::overflow_error、std::underflow_error、std::regex_error和std::system_error,表示运行期间不可预测的错误。4. 内存相关异常std::bad_alloc在new失败时抛出,直接继承自std::exception。5. 类型转换异常包括std::bad_cast(dynamic_cast失败时抛出)和std::bad_typeid(对nullptr使用typeid时可能抛出)。6. 异常处理相关异常有std::bad_exception(用于意外异常处理,已弃用)和std::nested_exception(支持嵌套异常传递)。7. 继承关系上,std::bad_alloc、std::bad_cast、std::bad_typeid、std::bad_exception和std::nested_exception均直接继承自std::exception,而非通过logic_error或runtime_error。8. 使用建议包括优先捕获具体异常类型再捕获基类、不依赖what()返回文本做逻辑判断、自定义异常应继承std::runtime_error或std::logic_error,并确保what()函数为noexcept。该体系设计清晰,覆盖常见错误场景,合理使用可显著提升程序健壮性和可维护性。

标准库抛出哪些异常 std exception类体系分析

C++标准库中的异常体系以

std::exception

为核心基类,所有标准异常都派生自它。了解这一类体系有助于编写更健壮的异常处理代码。以下是标准库中常见的异常类及其继承关系的详细分析。

一、std::exception 类体系概览

std::exception

是所有标准异常的基类,定义在


头文件中。它提供了一个虚函数:

virtual const char* what() const noexcept;

该函数返回描述异常原因的C风格字符串。

标准异常主要分为两大类:

逻辑错误(logic_error):程序逻辑可检测到的错误,通常在运行前就可发现。运行时错误(runtime_error):运行过程中发生的错误,无法在编译时预测。

二、常见的标准异常类及其用途

1. 逻辑错误(继承自

std::logic_error

std::logic_error

派生自

std::exception

,用于表示违反程序逻辑的错误。常见子类包括:

std::domain_error

表示参数超出了函数定义域。例如数学函数传入非法值。

std::invalid_argument

表示参数格式或类型不合法。例如

std::stoi("abc")

会抛出此异常。

std::length_error

表示试图创建一个超出容器最大长度的对象。例如

std::vector::resize()

超过

max_size()

std::out_of_range

表示访问越界,如

std::vector::at()

std::string::at()

访问无效索引。

std::future_error

std::future

std::promise

相关的错误,如重复设置值。

这些异常通常表示程序中的编程错误,应通过代码审查和输入校验避免。

2. 运行时错误(继承自

std::runtime_error

std::runtime_error

表示运行期间发生的、无法提前预测的错误。常见子类有:

std::range_error

表示计算结果超出有效范围,如数值转换溢出。

std::overflow_error

表示算术运算上溢,如浮点数过大。

std::underflow_error

表示算术运算下溢,如浮点数趋近于零但无法表示。

std::regex_error

正则表达式构造或匹配时出错。

std::system_error

(C++11 起)
封装系统级错误,如线程创建失败、文件打开失败等,通常配合

std::error_code

使用。

这类错误通常与外部环境或资源有关,需在运行时捕获并处理。

3. 内存相关异常

std::bad_alloc

new

操作符无法分配足够内存时抛出。它不继承自

std::exception

的子类,而是直接继承自

std::exception

示例:

try {    int* p = new int[1000000000000LL];} catch (const std::bad_alloc& e) {    std::cout << "内存分配失败: " << e.what() << std::endl;}

4. 类型转换异常

std::bad_cast

dynamic_cast

用于引用或指针类型转换失败时抛出(指针返回

nullptr

不抛异常,但引用失败会抛出)。

try {    Base& b = dynamic_cast(derived_obj);} catch (const std::bad_cast& e) {    std::cout << "类型转换失败: " << e.what() << std::endl;}
std::bad_typeid

当对

nullptr

指针使用

typeid

时抛出(C++17 前可能抛出,现在通常不抛,但标准仍保留此异常)。

5. 异常处理相关异常

std::bad_exception

用于意外异常处理机制(

std::set_unexpected

,已弃用),现在很少使用。

std::nested_exception

(C++11 起)
支持嵌套异常,允许捕获异常后再抛出并保留原始异常信息。配合

std::throw_with_nested

使用。

示例:

try {    try {        throw std::runtime_error("inner");    } catch (...) {        std::throw_with_nested(std::logic_error("outer"));    }} catch (const std::exception& e) {    // 可递归访问嵌套异常}

三、标准异常类的继承关系图(文字版)

std::exception├── std::logic_error│   ├── std::domain_error│   ├── std::invalid_argument│   ├── std::length_error│   ├── std::out_of_range│   └── std::future_error├── std::runtime_error│   ├── std::range_error│   ├── std::overflow_error│   ├── std::underflow_error│   ├── std::regex_error│   └── std::system_error├── std::bad_alloc├── std::bad_cast├── std::bad_typeid├── std::bad_exception└── std::nested_exception

注意:std::bad_alloc、std::bad_cast 等是直接继承自 std::exception,不通过 logic_error 或 runtime_error。

四、使用建议

优先捕获具体异常类型,再捕获基类。例如:

try {    // ...} catch (const std::invalid_argument& e) {    // 处理参数错误} catch (const std::runtime_error& e) {    // 处理运行时错误} catch (const std::exception& e) {    // 兜底处理}
what()

返回的字符串是实现定义的,内容可能简略,不要依赖其具体文本做逻辑判断。

自定义异常建议继承

std::runtime_error

std::logic_error

,便于统一处理。

使用

noexcept

时注意:

what()

函数承诺不抛异常,自定义异常也应遵守。

基本上就这些。标准异常体系设计清晰,覆盖了常见错误场景,合理使用能显著提升程序的健壮性和可维护性。

以上就是标准库抛出哪些异常 std exception类体系分析的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1472382.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月18日 19:34:24
下一篇 2025年12月18日 19:34:48

相关推荐

  • C++内存序类型 relaxed到seq_cst区别

    relaxed仅保证原子操作的原子性,不保证操作顺序,适合性能敏感且逻辑独立的场景;seq_cst提供全局一致的顺序保证,确保所有线程看到相同的操作序列,适合正确性优先的场景。两者核心区别在于对操作顺序的约束强度,选择需权衡性能与可预测性。 C++的 memory_order_relaxed 和 m…

    2025年12月18日
    000
  • C++14泛型lambda auto参数模板应用

    泛型lambda通过auto参数自动推断类型,避免了传统模板显式声明的冗余,使代码更简洁。例如,auto add = [](auto a, auto b) { return a + b; }; 比模板版本更短且易读。它在算法库(如std::transform)、函数式编程和通用比较函数中特别有用,可…

    2025年12月18日
    000
  • C++ if初始化语句 条件作用域控制改进

    C++17引入if和switch初始化语句以限制变量作用域,提升代码安全与可读性。1. 变量在if/switch条件中声明,作用域仅限语句块内,避免命名冲突与资源滥用。2. 支持智能指针等资源的自动管理,防止内存泄漏。3. 使代码更简洁,如结合find查找容器元素,无需提前声明迭代器。4. 过度使用…

    2025年12月18日
    000
  • C++文本编辑器开发 基础文件操作功能

    文件操作功能是C++文本编辑器核心,包括打开、读取、保存和另存为;2. 打开读取使用std::ifstream逐行读取并处理编码;3. 保存另存为使用std::ofstream写入内容并记录路径;4. 示例代码展示文件读写基本实现。 开发一个C++文本编辑器时,基础文件操作功能是核心部分,主要包括文…

    2025年12月18日
    000
  • C++ span容器 连续序列视图实现

    std::span通过提供统一、安全的非拥有式视图,解决了C++中连续内存操作的碎片化与安全隐患。它封装指针与长度,支持数组、vector、指针等多种类型,避免数据复制,减少重载与越界风险,提升函数接口的简洁性与健壮性,但需注意其不拥有数据,防止悬空引用。 C++ std::span 是一个轻量级的…

    2025年12月18日
    000
  • C++ STL multiset和set有何不同 分析允许重复元素的关联容器

    set和multiset的核心区别在于元素唯一性:1.set不允许重复元素,插入相同值时第二个会被忽略;2.multiset允许重复值存在,所有插入都会保留。此外,插入操作返回类型不同:set的insert()返回pair,而multiset只返回iterator。删除操作也不同:set用erase…

    2025年12月18日 好文分享
    000
  • C++数组初始化列表 统一初始化语法应用

    C++11引入统一初始化语法,使用花括号{}可安全初始化数组,避免窄化转换,支持自动推导大小和多维数组嵌套初始化,提升代码一致性与安全性。 在C++中,数组的初始化方式随着C++11引入的统一初始化语法(也称为列表初始化)变得更加灵活和安全。使用花括号 {} 的初始化方式可以适用于数组、结构体、类等…

    2025年12月18日
    000
  • C++运算符有哪些种类 算术逻辑位运算说明

    C++运算符包括算术、逻辑、位运算等,用于执行计算和操作。算术运算符处理基本数学运算,注意整数除法截断和自增/自减前置后置区别;逻辑运算符支持短路求值,常用于条件判断;位运算符操作二进制位,适用于底层优化。运算符优先级和结合性决定表达式求值顺序,建议用括号明确意图。常见陷阱有整数除法、短路副作用、有…

    2025年12月18日
    000
  • C++内存池如何实现 自定义分配器开发指南

    内存池通过预分配大块内存并管理空闲链表,减少系统调用开销,适用于高频小对象分配。1. 实现固定大小内存块的分配与回收;2. 设计兼容STL的自定义分配器,支持vector等容器;3. 优化方向包括多级池、线程局部存储、对齐处理和调试支持。注意C++17后与SSO的兼容性问题。 内存池的核心目标是减少…

    2025年12月18日
    000
  • C++指针类型转换 static_cast和reinterpret_cast

    static_cast用于安全的类型相关转换,如基类与派生类间指针转换;reinterpret_cast则重新解释指针的位模式,适用于低层编程但风险高,二者不可互换,应优先使用static_cast。 在C++中,指针类型转换是一个常见但需要谨慎处理的操作。static_cast 和 reinter…

    2025年12月18日
    000
  • C++内存访问冲突 调试诊断工具使用

    C++内存访问冲突调试需结合静态分析(如clang-tidy)、动态检测(如Valgrind、ASan)、调试器(GDB)和代码审查等手段,尽早发现并定位问题,避免程序崩溃。 C++内存访问冲突的调试诊断,核心在于尽早发现并定位问题,避免程序崩溃或产生难以追踪的错误行为。有效的工具和方法结合,能显著…

    2025年12月18日
    000
  • C++模块化编程 替代头文件新方法

    C++20模块通过import和export机制替代#include,解决头文件带来的编译慢、宏污染、封装差等问题,提升编译效率与代码可维护性。 C++模块化编程,简而言之,就是用C++20引入的模块(Modules)机制来替代我们沿用了几十年的头文件(Header Files)包含方式。这不仅仅是…

    2025年12月18日
    000
  • C++内存访问冲突 数据竞争检测与处理

    数据竞争指多线程无同步地访问同一内存且至少一写,导致未定义行为;内存访问冲突还包括越界、悬垂指针等。使用ThreadSanitizer可检测竞争,配合互斥锁、原子操作、线程局部存储和RAII锁管理可有效避免,结合日志与断言辅助调试。 在C++多线程编程中,内存访问冲突和数据竞争是常见且危险的问题。它…

    2025年12月18日
    000
  • C++内存拷贝如何优化 memcpy与移动语义对比

    答案:memcpy适用于POD类型的大块数据高效复制,但受限于类型安全和资源管理;移动语义则通过转移资源所有权,安全高效地处理复杂对象。应根据数据类型选择:原始数据用memcpy,对象传递用移动语义,避免对非POD类型滥用memcpy,结合编译器优化实现最佳性能。 在C++中,内存拷贝是一个常见但可…

    2025年12月18日
    000
  • C++机器学习环境如何配置 TensorFlow C++ API安装

    配置C++机器学习环境,特别是安装TensorFlow C++ API,坦白说,这活儿比Python环境要复杂得多,但一旦搞定,那种性能和部署的掌控感是Python难以比拟的。核心在于正确处理依赖、编译流程和链接问题,它要求你对C++的构建系统和库管理有更深的理解。 解决方案 要搭建一个能跑Tens…

    2025年12月18日
    000
  • C++循环优化技巧 减少分支预测失败

    循环展开可减少条件判断频率,降低分支预测失败概率;2. 使用位运算替代条件跳转可避免分支预测开销,提升循环执行效率。 在C++性能优化中,循环是重点区域,尤其是减少分支预测失败能显著提升执行效率。现代CPU依赖流水线和分支预测来提高指令吞吐,一旦发生预测错误,会导致流水线清空,带来性能损失。循环中频…

    2025年12月18日
    000
  • C++函数返回指针 局部变量地址问题分析

    返回局部变量地址会导致未定义行为,因为局部变量在函数结束时被销毁,指针指向已释放的栈内存,访问该指针可能引发程序崩溃或数据错误。 在C++中,函数返回指针时,如果返回的是局部变量的地址,会引发严重的运行时错误或未定义行为。这是因为局部变量的生命周期仅限于函数执行期间,函数结束时其内存空间会被自动释放…

    2025年12月18日
    000
  • C++结构体如何定义 struct关键字基本语法

    C++中定义结构体使用struct关键字,可组合不同类型数据,支持成员函数、构造函数及嵌套结构体,struct与class区别主要在默认访问权限,通常struct用于数据封装,class用于复杂行为抽象。 C++中定义结构体,核心就是使用 struct 关键字来创建一种自定义的数据类型,它能把不同类…

    2025年12月18日
    000
  • C++文件比较实现 逐字节对比算法

    逐字节文件比较通过二进制模式逐字节比对文件内容,确保完全一致,适用于完整性校验;C++实现中使用std::ifstream配合缓冲区和std::memcmp提升效率,并预检文件大小以快速判断差异。 文件比较,尤其是逐字节对比,核心在于确保两个文件内容是否完全一致。这通常用于验证文件完整性、备份校验,…

    2025年12月18日
    000
  • C++范围for循环 基于迭代器的语法糖

    C++范围for循环是语法糖,编译时展开为迭代器循环,提升代码可读性和安全性;通过实现begin()/end()可使自定义容器支持范围for;需避免循环中修改容器、注意临时对象生命周期,推荐使用const auto&或auto&;C++20 Ranges库结合视图适配器实现声明式数据…

    2025年12月18日
    000

发表回复

登录后才能评论
关注微信