C++基础与深度解析 | 异常处理 | 枚举与联合 | 嵌套类与局部类 | 嵌套名字空间与匿名名字空间 | 位域与volatile关键字
文章目录
- 一、异常处理
- 二、枚举与联合
- 三、嵌套类与局部类
- 四、嵌套名字空间与匿名名字空间
- 五、位域与volatile关键字
一、异常处理
异常处理用于处理程序在调用过程中的非正常行为。
-
传统的处理方法:传返回值表示函数调用是否正常结束。
例如,返回
0
表示成功,非0
表示失败。这种方法的缺点是函数的返回值被错误处理逻辑占用,不能用于其他目的。这种方法有局限性
-
C++ 中的处理方法:通过关键字 try/catch/throw 引入异常处理机制
通过
try/catch/throw
引入了结构化的错误处理机制,使得错误处理逻辑与正常逻辑分离,提高了代码的可读性和可维护性。C++异常处理的关键组件:
-
throw关键字
throw
关键字用于抛出一个异常。它后面可以跟任意类型的表达式,该表达式的结果将被用作异常对象 -
try块
try
块包含了可能会抛出异常的代码。如果try
块中的代码抛出了异常,那么与之匹配的catch
块将被执行。 -
catch块
catch
块用于捕获并处理异常。可以有多个catch
块来捕获不同类型的异常。 -
异常类
C++标准库中定义了一些基本的异常类,如
std::exception
、std::runtime_error
、std::logic_error
等
-
异常触发时的系统行为—栈展开:
-
抛出异常后续的代码不会被执行
一旦抛出异常,
throw
语句之后的代码将不会被执行。控制流会立即转移到异常处理机制。 -
局部对象会按照构造相反的顺序自动销毁
在栈展开过程中,局部对象(包括由
new
分配的对象)会按照它们构造的相反顺序自动销毁。这是为了保证资源的正确释放,防止内存泄漏。 -
系统尝试匹配相应的 catch 代码段
-
如果找到匹配的
catch
块:- 执行
catch
块中的异常处理逻辑。 - 异常被“捕获”后,
catch
块之后的代码会继续执行。
- 执行
-
如果没有找到匹配的
catch
块:-
栈展开会继续进行,直到找到匹配的
catch
块或者退出当前函数。 -
如果当前函数中没有找到匹配的
块,栈展开会继续,直到:
-
找到一个匹配的
catch
块。 -
达到
main
函数。如果在
main
函数之前的所有函数中都没有找到匹配的catch
块,程序将退出main
函数。如果程序在退出main
函数之前没有捕获到异常,std::terminate
函数将被调用。这通常会导致程序立即终止。
-
-
-
异常对象:
- 系统会使用抛出的异常拷贝初始化一个临时对象,称为异常对象
- 异常对象会在栈展开过程中被保留,并最终传递给匹配的 catch 语句
try / catch语句块:
-
一个 try 语句块后面可以跟一到多个 catch 语句块(至少跟一个)
-
每个 catch 语句块用于匹配一种类型的异常对象
可以有多个
catch
块,每个用于处理不同类型的异常。 -
catch 语句块的匹配按照从上到下进行
catch
块按照它们在代码中出现的顺序(从上到下)进行匹配。一旦找到匹配的异常类型,就执行相应的catch
块,忽略后面的catch
块。 -
使用 catch(…) 匹配任意异常
catch(...)
是一个通用的异常捕获器,它可以捕获任何类型的异常,包括未被前面的catch
块捕获的异常。 -
在 catch 中调用 throw 继续抛出相同的异常
在
catch
块中,可以使用throw;
(不带参数)来重新抛出当前捕获的异常,这将导致继续搜索外层catch
块。
示例:
#include <iostream>struct Str{};
struct Base{};
struct Derive : Base{};void f1()
{int x;Str obj;//throw Derive{}; //打印Derive exception is called in f2 throw Str{}; //打印exception is called in f2
}void f2()
{int x2;Str obj2;try{f1();}catch(Derive& e){std::cout << "Derive exception is called in f2 " << "\n";}catch(Base& e){std::cout << "Base exception is called in f2 " << "\n";}catch(...){std::cout << "exception is called in f2" << "\n";throw; //重新抛出当前捕获的异常}std::cout << "other logic in f2.\n";
}void f3()
{try{f2(); }catch(Str& e){std::cout << "exception is called in f2" << "\n";}
}int main()
{f3();
}
在一个异常未处理完成时抛出新的异常会导致程序崩溃:
- 不要在析构函数或 operator delete 函数重载版本中抛出异常
- 通常来说, catch 所接收的异常类型为引用类型
异常与构造、析构函数:
-
使用 function-try-block保护初始化逻辑
在C++中,function-try-block允许你在函数的初始化列表和函数体中使用
try
和catch
。这在构造函数中特别有用,因为它可以保护对象的初始化代码。示例:
#include <iostream>struct Str {Str() { throw 100; } }class Resource { public:Resource() try : m_str(){}catch(int){std::cout << "Exception is catched at Resource::Resource" << std::endl;throw;}private:Str m_str; };int main() {try{Resource obj; }catch(int){std::cout << "Exception is catched at main" << std::endl;} }
运行结果:
Exception is catched at Resource::Resource Exception is catched at main
-
在构造函数中抛出异常:
-
已经构造的成员对象会被销毁
如果在构造函数中抛出异常,已经构造的成员对象将按照它们构造的相反顺序自动销毁。
-
类本身的析构函数不会被调用
如果异常是在对象的构造过程中抛出的,并且没有被捕获,那么类的析构函数不会被调用。这是因为对象被视为未完全构造,因此析构函数不适用。
-
局部对象的销毁
如果对象是局部的(即在栈上),异常抛出时,局部对象会自动销毁,但不会调用其析构函数。
-
动态分配对象的销毁
如果对象是动态分配的(即使用
new
),在构造函数中抛出异常且未被捕获时,需要手动释放分配的内存,因为析构函数不会被调用。
-
描述函数是否会抛出异常:
-
如果函数不会抛出异常,则应表明,从而为系统提供更多的优化空间
- C++ 98 的方式:
- throw() :表明不会抛出异常
- throw(int, char):表明可能抛出异常,显式给定了要抛出异常的类型
- C++11 后的改进:
- noexcept :表明不会抛出异常
- noexcept(false):表明可能抛出异常,不需要显式给定会抛出哪种类型的异常
- C++ 98 的方式:
-
noexcept
- 限定符:接收 false / true 表示是否会抛出异常
- 操作符:接收一个表达式,根据表达式是否可能抛出异常返回 false/true
- 在声明了 noexcept 的函数中抛出异常会导致 terminate 被调用,程序终止
- 不作为函数重载依据,但函数指针、虚拟函数重写时要保持形式兼容
示例:
#include <iostream>void fun2()
{}void fun() noexcept(noexcept(fun2()))
{fun2();
}int main()
{std::cout << noexcept(fun()) << std::endl;
}
二、枚举与联合
三、嵌套类与局部类
四、嵌套名字空间与匿名名字空间
五、位域与volatile关键字
相关文章:
C++基础与深度解析 | 异常处理 | 枚举与联合 | 嵌套类与局部类 | 嵌套名字空间与匿名名字空间 | 位域与volatile关键字
文章目录 一、异常处理二、枚举与联合三、嵌套类与局部类四、嵌套名字空间与匿名名字空间五、位域与volatile关键字 一、异常处理 异常处理用于处理程序在调用过程中的非正常行为。 传统的处理方法:传返回值表示函数调用是否正常结束。 例如,返回 0 表示…...

番外篇 | 利用华为2023最新Gold-YOLO中的Gatherand-Distribute对特征融合模块进行改进
前言:Hello大家好,我是小哥谈。论文提出一种改进的信息融合机制Gather-and-Distribute (GD) ,通过全局融合多层特征并将全局信息注入高层,以提高YOLO系列模型的信息融合能力和检测性能。通过引入MAE-style预训练方法,进一步提高模型的准确性。🌈 目录 🚀1.论文解…...
python记录之字符串
在Python中,字符串是一种非常常见且重要的数据类型,用于存储文本信息。下面,我们将对Python字符串进行深入的讲解,包括其基本操作、常见方法、格式化以及高级特性。 1. 字符串的创建 在Python中,字符串可以通过单引号…...

Elasticsearch 认证模拟题 - 15
一、题目 原索引 task1 的字段 title 字段包含单词 The,查询 the 可以查出 1200 篇文档。重建 task1 索引为 task1_new,重建后的索引, title 字段查询 the 单词,不能匹配到任何文档。 PUT task1 {"mappings": {"…...
g++ 预处理 编译 汇编 链接 命令
g 预处理 编译 汇编 链接 命令 在命令行中使用 g 预处理、编译、汇编和链接源代码文件通常遵循以下步骤: 预处理(Preprocessing):将源代码文件转换为经过预处理器处理的中间文件。 g -E source.cpp -o source.i 编译ÿ…...
计算机视觉中的low-level与 high-level任务
文章目录 low-level任务high-level任务区别联系others参考在计算机视觉领域中,low-level任务和high-level任务是两个重要的概念,他们分别涉及图像处理和分析的不同的层次。 low-level任务 low-level任务主要关注的是图像的底层特征,如颜色、纹理、边缘、形状等。通常涉及对…...

安徽京准NTP时钟系统:GPS北斗卫星授时下的生活重塑
安徽京准NTP时钟系统:GPS北斗卫星授时下的生活重塑 安徽京准NTP时钟系统:GPS北斗卫星授时下的生活重塑 时间的流逝自古以来时钟都是人类生活与活动的基础。然而,随着科技的进步,我们对时间管理和测量的方法已经发生了翻天覆地的变…...
图论第8天
685.冗余连接II 这题需要考虑两种情况: 1.两个输入 2.没有两个输入就是有成环 class Solution { public:static const int N 1005;int father[N];int n;void init(){for (int i 0; i < n; i){father[i] i;}}int find(int x){return x father[x] ? x : f…...
Python怎么配置环境变量:深度探索与实战指南
Python怎么配置环境变量:深度探索与实战指南 在Python编程的世界中,环境变量的配置是一个至关重要的步骤。它不仅影响着Python解释器的运行,还关系到各种第三方库和工具的使用。本文将带你深度探索如何配置Python的环境变量,并为…...

计网期末复习指南(六):应用层(DNS、FTP、URL、HTTP、SMTP、POP3)
前言:本系列文章旨在通过TCP/IP协议簇自下而上的梳理大致的知识点,从计算机网络体系结构出发到应用层,每一个协议层通过一篇文章进行总结,本系列正在持续更新中... 计网期末复习指南(一):计算…...

HTML做成一个炫酷跳动爱心的页面
大家好,今天制作制作一个炫酷跳动爱心的页面! 先看具体效果: 要创建一个炫酷跳动爱心的HTML页面,你可以使用HTML、CSS和JavaScript的组合。以下是一个简单的示例,它使用CSS动画和JavaScript来实现跳动效果。 首先&…...

React + SpringBoot实现图片预览和视频在线播放,其中视频实现切片保存和分段播放
图片预览和视频在线播放 需求描述 实现播放视频的需求时,往往是前端直接加载一个mp4文件,这样做法在遇到视频文件较大时,容易造成卡顿,不能及时加载出来。我们可以将视频进行切片,然后分段加载。播放一点加载一点&am…...

Suse Linux ssh配置免密后仍需要输入密码
【问题描述】 Suse Linux已经配置了ssh免密,但无法ssh到目标服务器。 对自身的ssh登陆也需要输入密码。 系统–Suse 15 SP5 【重现步骤】 1.使用ssh-keygen -t rsa生产key文件 2.使用ssh-copy-id拷贝public key到目标机器(或者自身) 3.配置成功后ssh 目标时仍需要输…...

apifox 生成签名
目录 前言准备编写签名脚本签名说明捋清思路编码获取签名所需的参数生成签名将签名放到合适的位置完整代码 在apifox中配置脚本新增公共脚本引用公共脚本添加环境变量 参考 前言 略 准备 查看apifox提供的最佳实践文章:接口签名如何处理 编写签名脚本 签名说明…...
介绍建造者模式
建造者模式 将一个复杂对象的创建与它的表示分离,使得同样的构建过程可以创建不同的表示 四种角色 Product 产品角色 指的是一个具体的产品对象Builder 抽象建造者 创建一个产品对象的各个部件的接口/抽象类ConcreteBuilder 具体建造者 实现或继承抽象建造者接口…...

【全部更新完毕】2024全国大学生数据统计与分析竞赛B题思路代码文章教学数学建模-电信银行卡诈骗的数据分析
电信银行卡诈骗的数据分析 摘要 电信银行卡诈骗是当前社会中严重的犯罪问题,分析电信银行卡交易数据,找出高风险交易特征,建立预测模型,将有助于公安部门和金融机构更好地防范诈骗行为,保障用户的财产安全。 针对问…...

【应用浅谈】Odoo的库存计价与产品成本(三)
序言:时间是我们最宝贵的财富,珍惜手上的每个时分 Odoo的库存(Stock)模块拥有众多功能,其中库存计价是一项非常重要的功能,原生的成本方法分三种:【标准成本】,【平均成本】,【先进先出】&#…...

数据结构之ArrayList与顺序表(下)
找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程(ಥ_ಥ)-CSDN博客 所属专栏:数据结构(Java版) 目录 ArrayList的具体使用 118. 杨辉三角 扑克洗牌算法 接上篇:数据结构之ArrayLis…...
openi启智社区 aarch64 npu环境安装飞桨paddlepaddle和PaddleNLP(失败)
以前在启智社区都是编译安装飞桨,这回看到飞桨提供了npu安装包,兴冲冲的以为安装很简单。 之所以安装飞桨,是因为想在启智社区的启智大脑调试环境使用最新的PaddleNLP,结果报错:No module named paddle.nn.layer.laye…...

【漏洞复现】多客圈子论坛系统 httpGet 任意文件读取漏洞
0x01 产品简介 多客圈子论坛系统是一种面向特定人群或特定话题的社交网络,它提供了用户之间交流、分享、讨论的平台。在这个系统中,用户可以创建、加入不同的圈子,圈子可以是基于兴趣、地域、职业等不同主题的。用户可以在圈子中发帖、评论、…...

使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...

Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

C++--string的模拟实现
一,引言 string的模拟实现是只对string对象中给的主要功能经行模拟实现,其目的是加强对string的底层了解,以便于在以后的学习或者工作中更加熟练的使用string。本文中的代码仅供参考并不唯一。 二,默认成员函数 string主要有三个成员变量,…...
ThreadLocal 源码
ThreadLocal 源码 此类提供线程局部变量。这些变量不同于它们的普通对应物,因为每个访问一个线程局部变量的线程(通过其 get 或 set 方法)都有自己独立初始化的变量副本。ThreadLocal 实例通常是类中的私有静态字段,这些类希望将…...