【C++ 异常】深入探究C++的stdexcept类库


深入探究C++的stdexcept类库

引言

在C++编程中,异常处理是一个不可或缺的部分。C++标准库提供了一组用于异常处理的标准类,这些类都定义在<stdexcept>头文件中。本文将深入探讨这些异常类,以及它们如何与C++的异常处理机制相结合。

“C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off.” — Bjarne Stroustrup, 《The C++ Programming Language》
C++语言本身或者标准库抛出的异常都是exception的子类,称为标准异常。捕获所有的标准异常的语句.

概览

在C++中,<stdexcept>头文件定义了一系列用于标准异常处理的类。这些类都继承自std::exception基类。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

类名 描述 常用场景
std::exception 基础异常类 作为其他异常类的基类
std::logic_error 逻辑错误 程序逻辑错误
std::runtime_error 运行时错误 程序运行时出现的错误
std::invalid_argument 无效参数 函数参数无效
std::out_of_range 越界 访问数组、向量等越界

std::exception

try{
    
    
    //可能抛出异常的语句
}catch(exception &e)  //使用引用是为了提高效率,不然需要经过一次对象拷贝过程。
{
    
    
    //处理异常的语句
}

std::exception是所有标准异常类的基类。它提供了一个名为what()的成员函数,用于返回一个C风格的字符串,描述异常的详情。

#include <iostream>
#include <stdexcept>

int main() {
    
    
    try {
    
    
        throw std::exception("An exception occurred");
    } catch (const std::exception& e) {
    
    
        std::cout << e.what() << std::endl;  // Output: An exception occurred
    }
    return 0;
}

在这个例子中,我们使用throw关键字抛出一个std::exception对象,并在catch块中捕获它。

– exception 类的直接派生类

异常名称 说 明
logic_error 程序逻辑问题.
runtime_error 只有在运行时才能检测出的问题.
bad_alloc 使用 new 或 new[ ] 分配内存失败时抛出的异常。
bad_typeid 使用 typeid 操作一个 NULL 指针,而且该指针是带有虚函数的类,这时抛出 bad_typeid 异常。
bad_cast 使用 dynamic_cast 转换失败时抛出的异常。
ios_base::failure io 过程中出现的异常。
bad_exception 这是个特殊的异常,如果函数的异常列表里声明了 bad_exception 异常,当函数内部抛出了异常列表中没有的异常时,如果调用的 unexpected() 函数中抛出了异常,不论什么类型,都会被替换为 bad_exception 类型。

std::logic_error 与 std::runtime_error

这两个类是std::exception的直接子类,用于处理逻辑错误和运行时错误。

#include <stdexcept>

void foo(int x) {
    
    
    if (x < 0) {
    
    
        throw std::logic_error("Negative value");
    }
    if (x > 100) {
    
    
        throw std::runtime_error("Value too large");
    }
}

在这个例子中,foo函数接受一个整数x作为参数。如果x是负数,函数会抛出一个std::logic_error异常。如果x大于100,函数会抛出一个std::runtime_error异常。

  • logic_error 的派生类(逻辑错误)
异常名称 说 明
length_error 试图生成一个超出该类型最大长度的对象时抛出该异常,例如 vector 的 resize 操作。
domain_error 参数的值域错误,主要用在数学函数中,例如使用一个负值调用只能操作非负数的函数。
out_of_range 超出有效范围。
invalid_argument 参数不合适。在标准库中,当利用string对象构造 bitset 时,而 string 中的字符不是 0 或1 的时候,抛出该异常。
  • runtime_error 的派生类(运行时错误)
异常名称 说 明
range_error 计算结果超出了有意义的值域范围。
overflow_error 算术计算上溢。
underflow_error 算术计算下溢。

std::invalid_argument 与 std::out_of_range

这两个类是std::logic_error的子类,用于更具体的异常场景。

#include <vector>
#include <stdexcept>

void bar(std::vector<int>& vec, int index) {
    
    
    if (index < 0) {
    
    
        throw std::invalid_argument("Negative index");
    }
    if (index >= vec.size()) {
    
    
        throw std::out_of_range("Index out of range");
    }
}

在这个例子中,bar函数接受一个std::vector<int>和一个索引index。如果索引是负数,函数会抛出一个std::invalid_argument异常。如果索引超出向量的大小,函数会抛出一个std::out_of_range异常。

源码解析

在GCC编译器中,<stdexcept>的实现可以在/usr/include/c++/版本号/bits/stdexcept.h中找到。这些异常类大多数都是简单的类,主要是通过继承std::exception并实现what()函数来提供异常信息。

总结

异常处理是编程中非常重要的一环,而C++通过<stdexcept>提供了一套完善的标准异常类,使得异常处理变得更加方便和规范。这不仅提高了代码的健壮性,也使得程序更容易维护。

“We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.” — Donald Knuth

通过深入了解这些异常类,我们可以更好地理解程序中可能出现的各种问题,并采取相应的措施。这不仅是对代码的一种保护,也是对程序员思维严谨性的一种体现。

希望本文能帮助你更深入地了解C++的异常处理机制。

结语

在我们的编程学习之旅中,理解是我们迈向更高层次的重要一步。然而,掌握新技能、新理念,始终需要时间和坚持。从心理学的角度看,学习往往伴随着不断的试错和调整,这就像是我们的大脑在逐渐优化其解决问题的“算法”。

这就是为什么当我们遇到错误,我们应该将其视为学习和进步的机会,而不仅仅是困扰。通过理解和解决这些问题,我们不仅可以修复当前的代码,更可以提升我们的编程能力,防止在未来的项目中犯相同的错误。

我鼓励大家积极参与进来,不断提升自己的编程技术。无论你是初学者还是有经验的开发者,我希望我的博客能对你的学习之路有所帮助。如果你觉得这篇文章有用,不妨点击收藏,或者留下你的评论分享你的见解和经验,也欢迎你对我博客的内容提出建议和问题。每一次的点赞、评论、分享和关注都是对我的最大支持,也是对我持续分享和创作的动力。


阅读我的CSDN主页,解锁更多精彩内容:泡沫的CSDN主页
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_21438461/article/details/132949528