【C++篇】 异常处理

目录

1,异常的概念及使用

1.1,异常的概念

1.2,异常的抛出和捕获

1.3,栈展开

1.4,异常的重新抛出

1.5,异常安全问题

1.6,异常规范

2,标准库中的异常

小结:


1,异常的概念及使用

1.1,异常的概念

异常处理是C++用于管理 程序运行时错误的核心机制,通过try,catch,throw等关键字实现。它允许将错误检测与处理逻辑分离,提升代码的可读性和健壮性。

1.2,异常的抛出和捕获

  • 程序出现问题时,我们通过抛出(throw)一个对象来引发一个异常,该对象的类型和当前的调用链决定了应该由哪个catch来捕获处理该异常。

  • 当throw执行时,throw后面的代码不再执行。程序的执行从throw位置跳到与之匹配的catch模块。catch可能是同一个函数中的一个局部的catch,也可能是调用链中另一个函数中的catch。一旦程序开始异常处理,沿着调用链的对象都将被销毁。
  • 抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的异常对象可能是一个局部对象,所以会生成一个拷贝对象,拷贝对象再catch子句后销毁。

代码示例:

#include <iostream>
#include <stdexcept>

double divide(int a, int b) {
    if (b == 0) {
        throw std::runtime_error("除数不能为零!");   //抛出异常对象
    }
    return a / b;
}

int main() {
    try {
        std::cout << divide(10, 0) << std::endl;
    } catch (const std::runtime_error& e) {   //捕获异常,处理异常
        std::cerr << "错误: " << e.what() << std::endl;
    }
    return 0;
}
// 输出:错误: 除数不能为零!

1.3,栈展开

  • 抛出 异常后,程序暂停当前函数的执行,开始寻找与之匹配的catch子句,首先检查throw是否再try块内部,如果在则查找匹配的catch语句,如果由匹配的,则跳到catch地方进行处理。
  • 如果当前函数没有try/catch子句,或者有但是类型不匹配,退出当前函数,继续在外层调用函数链中查找,上述查找catch的过程称为栈展开。

  • 如果到达main函数,依旧没有找到匹配的catch子句,则程序会调用terminate函数终止程序。有时候达到main函数,还没有找到匹配的,而我们是不希望终止程序的,所以main函数最后一般都使用catch(...),它可以捕获任意类型的异常,但不知道异常错误是什么
  • 如果找到匹配的catch子句处理后,catch子句代码会继续执行。

1.4,异常的重新抛出

有时catch到一个异常对象 后,需要对错误进行分类,其中的某种异常错误 需要进行特殊处理,其他异常则重新抛出给外层调用链处理。捕获异常后重新抛出,直接throw,就可以把捕获的对象重新抛出。

常见应用场景:

1,中间层处理部分逻辑

在多层调用中,中间层捕获异常后记录日志或释放资源,但不处理异常的根本原因:

void middleLayer() {
    try {
        someRiskyOperation();
    } catch (const std::exception& e) {
        logError(e.what()); // 记录日志
        throw; // 重新抛出,让上层处理
    }
}

2,包装异常

捕获原始异常后,抛出一个新的异常类型(如自定义异常),同时保留原始异常信息:

try {
    // ...
} catch (const DatabaseException& e) {
    throw MyAppException("Database error: " + std::string(e.what()));

3,跨线程异常传递

使用 std::exception_ptr 保存异常,稍后在另一线程中重新抛出:

std::exception_ptr eptr;
try {
    // 可能抛出异常的代码
} catch (...) {
    eptr = std::current_exception(); // 捕获并保存异常
}

// 在另一个线程中重新抛出
if (eptr) {
    std::rethrow_exception(eptr);
}

1.5,异常安全问题

  • 异常抛出后,后面的代码就不在执行了,前面申请了资源(内存),后面进行释放。但是中间可能会抛异常,导致资源没有释放,这里就由于异常引发了资源泄露,产生安全性的问题。这里需要使用智能指针的RAII方式解决。
  • 还有析构函数中,如果抛出异常也要谨慎处理,比如要释放 10个资源,释放到第5个时抛出异常,导致后面的资源没有释放,导致资源泄露了。

1.6,异常规范

C++11中 ,函数的参数列表后加一个noexcept表示该函数不会抛异常。但如果一个声明了noexcept的函数抛出了异常,程序会调用terminate终止程序。

noexcept还可以作为运算符去检测一个表达式是否会抛异常。

  • noexcept(expression):根据式表达的结果来决定是否可能抛出异常。如果表达式为 true,则表示不会抛出异常;如果为 false,则表示可能抛出异常。

2,标准库中的异常

C++标准库定义了一套自己的异常体系,基类是exception,所以我们在捕获异常时,捕获exception即可,要获取异常信息,调用what()函数,what()是一个虚函数,派生类可以重写。 

(1)C++标准库中常见的类型(继承自:std::exception)

  • std::logic_error:程序逻辑错误(如无效参数)。

  • std::runtime_error:运行时错误(如文件未找到)。

  • std::bad_alloc:内存分配失败(new失败时抛出)。

(2)自定义异常

通过继承std::exception创建自定义异常类:

class MyException : public std::exception {
public:
    MyException(const char* msg) : message(msg) {}
    const char* what() const noexcept override {
        return message.c_str();
    }
private:
    std::string message;
};

// 使用
throw MyException("自定义异常!");

小结:

(1)异常处理的性能影响

抛出异常时:栈展开(Stack Unwinding)和类型匹配会带来一定开销,不适合高频场景。

(2) 最佳实践

1,优先使用RAII(如智能指针):确保资源的自动释放

2,避免在析构函数中抛出异常:可能会导致程序终止(若异常未被捕获)

3,明确异常规格:使用noexcept标记不会抛异常的函数。

4,捕获异常按引用:避免对象切片如:catch (const std::exception& e)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/15089.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT修仙之路1-1--遇见QT

文章目录 遇见QT二、QT概述2.1 定义与功能2.2 跨平台特性2.3 优点汇总 三、软件安装四、QT工具介绍(重要)4.1 Assistant4.2 Designer4.3 uic.exe4.4 moc.exe4.5 rcc.exe4.6 qmake4.7 QTcreater 五、QT工程项目解析(作业)5.1 配置文件&#xff08;.pro&#xff09;5.2 头文件&am…

python实现情绪识别模块,并将模块封装成可执行文件

目录&#xff1a; 1.源码&#xff1a;2.情绪识别模型运行流程&#xff1a;3.模型封装需要注意的地方&#xff1a;4.未解决问题&#xff1a; 1.源码&#xff1a; https://gitcode.com/xyint/deep_learning.git 2.情绪识别模型运行流程&#xff1a; 需要获取用户摄像头权限&…

网络防御高级02-综合实验

web页面&#xff1a; [FW]interface GigabitEthernet 0/0/0 [FW-GigabitEthernet0/0/0]service-manage all permit 需求一&#xff0c;接口配置&#xff1a; SW2: [Huawei]sysname SW2 1.创建vlan [sw2]vlan 10 [sw2]vlan 20 2.接口配置 [sw2]interface GigabitEther…

Arbess基础教程-创建流水线

Arbess(谐音阿尔卑斯) 是一款开源免费的 CI/CD 工具&#xff0c;本文将介绍如何使用 Arbess 配置你的第一条流水线&#xff0c;以快速入门上手。 1. 创建流水线 根据不同需求来创建不同的流水线。 1.1 配置基本信息 配置流水线的基本信息&#xff0c;如分组&#xff0c;环境&…

MySQL下载过程

MySQL Enterprise Edition Downloads | Oracle mysql官方下载网址&#xff08;9.2版本&#xff09; 下面的示例是5.7的包&#xff0c;过程是一样的 port&#xff1a;3308&#xff08;默认的是3306&#xff0c;笔者下了一个占用了该端口&#xff09; root&#xff1a;123456 问题…

StochSync:可在任意空间中生成360°全景图和3D网格纹理

StochSync方法可以用于在任意空间中生成图像&#xff0c;尤其是360全景图和3D网格纹理。该方法利用了预训练的图像扩散模型&#xff0c;以实现零-shot生成&#xff0c;消除了对新数据收集和单独训练生成模型的需求。StochSync 结合了 Diffusion Synchronization&#xff08;DS&…

Windows逆向工程入门之汇编环境搭建

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 Visual Studio逆向工程配置 基础环境搭建 Visual Studio 官方下载地址安装配置选项(后期可随时通过VS调整) 使用C的桌面开发 拓展可选选项 MASM汇编框架 配置MASM汇编项目 创建新项目 选择空…

【多模态大模型】系列1:CLIP【多模态领域开山之作】

目录 1 模型结构2 伪代码3 Loss计算方法 官方网站&#xff1a;https://openai.com/index/clip/ 论文&#xff1a;Learning Transferable Visual Models From Natural Language Supervision GitHub&#xff1a;https://github.com/openai/CLIP Colab&#xff1a;https://colab.r…

SSA-TCN麻雀算法优化时间卷积神经网络时间序列预测未来Matlab实现

SSA-TCN麻雀算法优化时间卷积神经网络时间序列预测未来Matlab实现 目录 SSA-TCN麻雀算法优化时间卷积神经网络时间序列预测未来Matlab实现预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现SSA-TCN麻雀算法优化时间卷积神经网络时间序列预测未来&#xff08;优…

idea整合deepseek实现AI辅助编程

1.File->Settings 2.安装插件codegpt 3.注册deepseek开发者账号&#xff0c;DeepSeek开放平台 4.按下图指示创建API KEY 5.回到idea配置api信息&#xff0c;File->Settings->Tools->CodeGPT->Providers->Custom OpenAI API key填写deepseek的api key Chat…

k8s部署elasticsearch

前置环境&#xff1a;已部署k8s集群&#xff0c;ip地址为 192.168.10.1~192.168.10.5&#xff0c;总共5台机器。 1. 创建provisioner制备器&#xff08;如果已存在&#xff0c;则不需要&#xff09; 制备器的具体部署方式&#xff0c;参考我之前的文章&#xff1a;k8s部署rab…

(done) openMP学习 (Day13: 线程私有数据和如何支持库(Pi again),蒙特卡洛计算 Pi,线性同余法)

url: https://dazuozcy.github.io/posts/introdution-to-openmp-intel/#23-%E5%8F%AF%E6%80%95%E7%9A%84%E4%B8%9C%E8%A5%BF%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8Batomicsflushpairwise%E5%90%8C%E6%AD%A5%20 视频&#xff1a;https://www.bilibili.com/video/BV1SW411s7ST?s…

借助AI,轻松读好书

读书笔记 AI可以帮助我们写读书笔记&#xff0c;通过智能化的分类和标注技术&#xff0c;将我们的笔记进行分类整理&#xff0c;使其更加清晰易懂&#xff0c;帮助我们高效&#xff0c;准确&#xff0c;深入的总结和掌握书中的知识&#xff0c;实现更好的学习和成长。 《异类》…

【AIGC】语言模型的发展历程:从统计方法到大规模预训练模型的演化

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;语言模型的发展历程&#xff1a;从统计方法到大规模预训练模型的演化1 统计语言模型&#xff08;Statistical Language Model, SLM&#xff09;&#xff1a;统…

活动预告 |【Part1】Microsoft Azure 在线技术公开课:基础知识

课程介绍 参加“Azure 在线技术公开课&#xff1a;基础知识”活动&#xff0c;培养有助于创造新的技术可能性的技能并探索基础云概念。参加我们举办的本次免费培训活动&#xff0c;扩充自身的云模型和云服务类型知识。你还可以查看以计算、网络和存储为核心的 Azure 服务。 活…

python 语音识别方案对比

目录 一、语音识别 二、代码实践 2.1 使用vosk三方库 2.2 使用SpeechRecognition 2.3 使用Whisper 一、语音识别 今天识别了别人做的这个app,觉得虽然是个日记app 但是用来学英语也挺好的,能进行语音识别,然后矫正语法,自己说的时候 ,实在不知道怎么说可以先乱说,然…

C# OpenCvSharp 部署MOWA:多合一图像扭曲模型

目录 说明 效果 项目 代码 下载 参考 C# OpenCvSharp 部署MOWA&#xff1a;多合一图像扭曲模型 说明 算法模型的paper名称是《MOWA: Multiple-in-One Image Warping Model》 ariv链接 https://arxiv.org/pdf/2404.10716 效果 Stitched Image 翻译成中文意思是&…

【Java】线上故障排查实战

引言 JVM命令详细可以看前一篇文章&#xff0c;本篇文章基于之前的命令做一次简单的线上故障排查分析 JVM常见命令 实战 1. 一般显示都是Linux系统&#xff0c;我们排查winodows系统想知道CPU和内存使用情况&#xff0c;打开任务管理器就可以出现图形化界面&#xff0c;而L…

编译spring 6.2.2

如何编译Spring 6.2.2 下载spring 6.2.2 首先&#xff0c;下载spring 6.2.2&#xff0c;地址&#xff1a;下载 解压到你的目录下。 下载gradle 下载gradle&#xff0c;这是spring项目的依赖管理工具&#xff0c;本文下载的是8.12.1 gradle下载 下载合适的JDK 本文下载的是…

深度求索(DeepSeek)的AI革命:NLP、CV与智能应用的技术跃迁

Deepseek官网&#xff1a;DeepSeek 引言&#xff1a;AI技术浪潮中的深度求索 近年来&#xff0c;人工智能技术以指数级速度重塑全球产业格局。在这场技术革命中&#xff0c;深度求索&#xff08;DeepSeek&#xff09;凭借其前沿的算法研究、高效的工程化能力以及对垂直场景的…