GCC 9.4 编译error: catching polymorphic type ‘class std::bad_alloc’ by value [-Werror=catch-value=]

环境

lm@lm:~$ cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04.4 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04.4 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal



lm@lm:~$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/9/lto-wrapper
OFFLOAD_TARGET_NAMES=nvptx-none:hsa
<think>我们正在讨论C++标准库中的异常类型层次结构。用户的问题:std::exception是否包含std::range_errorstd::bad_alloc? 在C++标准库中,异常类型是通过继承层次来组织的。绝大多数标准库异常都派生自基类`std::exception`。 具体来说: - `std::range_error` 是 `std::runtime_error` 的派生类,而 `std::runtime_error` 又是 `std::exception` 的派生类。 - `std::bad_alloc` 直接继承自 `std::exception`。 因此,`std::range_error` 和 `std::bad_alloc` 都是 `std::exception` 的派生类。这意味着当我们捕获 `std::exception` 时,也会捕获到这些异常。 异常类层次结构(简化): ``` std::exception ├── std::bad_alloc ├── std::runtime_error │ └── std::range_error └── ... (其他异常,如std::logic_error等) ``` 所以,在异常捕获时: - 如果我们先捕获 `std::bad_alloc`,然后再捕获 `std::exception`,那么 `std::bad_alloc` 会被第一个catch块捕获,而 `std::range_error` 会被第二个catch块捕获(因为 `std::range_error` 不是 `std::bad_alloc` 的派生类,所以会继续匹配下一个catch块)。 - 如果我们只捕获 `std::exception`,那么无论是 `std::bad_alloc` 还是 `std::range_error`(包括其他从 `std::exception` 派生的异常)都会被捕获。 因此,回答用户的问题:是的,`std::exception` 包含(即作为基类,其派生类包含)`std::range_error` 和 `std::bad_alloc`。 但注意:在异常捕获时,通常建议先捕获更具体的异常(派生类),再捕获更一般的异常(基类)。例如: ```cpp try { // 可能抛出多种异常的操作 } catch (const std::bad_alloc& e) { // 处理内存分配失败 } catch (const std::range_error& e) { // 处理范围错误 } catch (const std::exception& e) { // 处理其他标准异常 } catch (...) { // 处理非标准异常 } ``` 这样,我们可以针对不同类型的异常进行不同的处理。 在用户提供的引用中,也提到了一些异常情况: - 引用[1]中提到了`std::bad_cast`,它同样继承自`std::exception`。 - 引用[2][3][4]都提到了`std::bad_alloc`,即内存分配失败。 因此,我们可以确认这些异常都属于`std::exception`的派生类。 最后,生成相关问题供用户进一步探索。 </think>### 关于 `std::exception` 的类型包含关系 在 C++ 标准库中,`std::exception` 是**所有标准异常类的基类**。其类型层次结构可以表示为: ``` std::exception ├── std::bad_alloc ├── std::logic_error │ └── std::out_of_range └── std::runtime_error └── std::range_error ``` 因此: 1. **`std::range_error` 继承链** `std::range_error` → `std::runtime_error` → `std::exception` ✔️ 明确包含在 `std::exception` 中[^1] 2. **`std::bad_alloc` 继承链** `std::bad_alloc` → `std::exception` ✔️ 直接继承自 `std::exception`[^2][^3][^4] ### 关键结论 $$ \boxed{\text{std::exception} \supset \text{std::range\_error}} $$ $$ \boxed{\text{std::exception} \supset \text{std::bad\_alloc}} $$ 当使用 `catch (const std::exception& e)` 时,会捕获: - 所有直接或间接继承自 `std::exception` 的异常 - 包括但不限于:`std::range_error`, `std::bad_alloc`, `std::runtime_error`, `std::bad_cast` 等 ### 异常捕获实践建议 ```cpp try { // 可能抛出异常的代码 } catch (const std::range_error& e) { // 优先捕获具体异常 // 处理范围错误 } catch (const std::bad_alloc& e) { // 优先捕获具体异常 // 处理内存分配失败 } catch (const std::exception& e) { // 通用捕获 // 处理其他标准异常 } catch (...) { // 应急处理 // 捕获非标准异常 } ``` ### 深层原理 1. **`std::exception` 的设计原则** C++ 标准库通过继承实现异常分类: ```mermaid classDiagram exception <|-- bad_alloc exception <|-- logic_error exception <|-- runtime_error runtime_error <|-- range_error ``` 2. **内存分配失败的特殊性** `std::bad_alloc` 直接继承基类,因为内存错误可能发生在任何操作中(包括异常处理流程自身) 3. **跨平台兼容性** 所有主流编译器(GCC/Clang/MSVC)严格遵循此继承层次,保证代码可移植性 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值