C++异常

1. 什么是异常?

异常是程序在运行时可能发生的、超出正常执行流程的事件(或错误)。例如:除以零、内存分配失败、文件不存在、无效的用户输入等。

C++ 提供了一套结构化的机制来抛出(throw)和捕获(catch)这些异常,从而将正常的业务逻辑与错误处理代码清晰地分离开。

2. 异常的抛出与捕获

  • 程序出现问题时,我们通过抛出(throw)⼀个对象来引发⼀个异常,该对象的类型以及当前的调⽤链决定了应该由哪个catch的处理代码来处理该异常。

  • catch通常捕获的是离抛出异常位置最近且与抛出对象类型匹配的,根据抛出对象的类型和内容,程序的抛出异常部分告知异常处理部分到底发⽣了什么错误。

  • 当throw执⾏时,throw后⾯的语句将不再被执⾏。程序的执⾏从throw位置跳到与之匹配的catch模块,catch可能是同⼀函数中的⼀个局部的catch,也可能是调⽤链中另⼀个函数中的catch,控制权从throw位置转移到了catch位置。这⾥还有两个重要的含义:1、沿着调⽤链的函数可能提早退出。2、⼀旦程序开始执⾏异常处理程序,沿着调⽤链创建的对象都将销毁。

  • 抛出异常对象后,会⽣成⼀个异常对象的拷⻉,因为抛出的异常对象可能是⼀个局部对象,所以会⽣成⼀个拷⻉对象,这个拷⻉的对象会在catch⼦句后销毁。

3. 栈展开

  • 栈展开是当异常被抛出后,为了找到匹配的 catch 块,C++ 运行时系统自动沿着函数调用链(即调用栈)向上回溯的过程。在这个过程中,它会析构所有已创建但尚未析构的局部对象

  • 这个过程确保了即使在异常发生时,资源也能被正确释放,避免了内存泄漏。

  • 对于使用 new 在堆上手动分配的对象,如果只有原始指针指向它,那么在栈展开过程中,这个对象不会被自动析构,会导致内存泄漏。

    • 解决方案:使用智能指针。
  • 如果到达main函数,依旧没有找到匹配的catch⼦句,程序会调⽤标准库的 terminate 函数终⽌程序。

  • 如果找到匹配的catch⼦句处理后,catch⼦句代码会继续执⾏。

4. 异常的一些注意事项

  • ⼀般情况下抛出对象和catch是类型完全匹配的,如果有多个类型匹配的,就选择离他位置更近的那个。

  • 类型完全匹配,但是也有一些例外情况。

    • 权限缩小的转换

    • 数组到指针的转换

    • 函数到函数指针的转换

    • 派生类到基类的转换(重要)

  • 异常处理的最后防线

    • 在C++异常处理中,如果异常一直传递到 main() 函数仍然没有被捕获,程序就会异常终止。除非发生无法恢复的严重错误,否则我们通常不希望程序这样突然结束。因此,最佳实践是在 main() 函数的最后使用 catch(...) 作为安全网。

    • int main() {
          try {
              // 程序主要逻辑
              runProgram();
          }
          catch (const std::exception& e) {
              // 捕获标准异常
              std::cerr << "标准异常: " << e.what() << std::endl;
          }
          catch (...) {
              // 捕获所有其他未知异常
              std::cerr << "发生未知异常!" << std::endl;
          }
          return 0;
      }
      
    • catch(…)的局限性

      • 能捕获任意类型的异常

      • 无法获取异常的具体信息

      • 不能知道异常的类型或内容

  • 异常的重新抛出。

    • 异常重新抛出是指在 catch 块中捕获异常后,再次抛出同一个异常,让外层的调用者继续处理。

    • 重新抛出使用 throw;

  • noexcept 是 C++11 引入的关键字,用于指定函数不会抛出异常

  • // 该函数承诺不会抛出任何异常
    void myFunction() noexcept {
        // 函数实现
        // 如果这里抛出了异常,程序会调用 std::terminate()
    }
    
  • 移动操作通常应该标记为 noexcept,移动操作标记为 noexcept 能够让标准库容器和算法安全地使用移动语义而不是拷贝语义,从而获得显著的性能提升。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐