C++Prime Plus(5)

article/2025/9/14 6:24:55

目录

  • 85.异常(1)异常处理机制
  • 86.异常(2)exception类
  • 87.RTTI(1)
  • 88.RTTI(2)
  • 89.类型转换运算符
  • 90.string类
  • 91.智能指针

85.异常(1)异常处理机制

异常:运行错误(比如无法打开文件,动态内存申请失败),导致程序无法继续正常运行;

处理异常的常用方法:

1.调用stdlib中的abort()函数:输出一个程序异常终止的信息,然后终止程序;
fig1
void abort(void) 用于中止程序执行,直接从调用的地方跳出;

2.利用函数的返回值报告错误;
fig2
其中,DBL_MAX是double型的最大值。

示例:
fig3
异常机制
遇到异常时,将控制权从程序的一个部分转移到另一个部分;

异常处理的组成部分
try块:用于标识可能抛出异常的程序块;
throw抛出异常:程序检测到异常时,跳出当前部分;
catch捕获异常:处理异常的程序;

示例:
fig4
将对象用作异常类型
throw可以抛出任何类型的值,catch捕获抛出值的类型(我们可以用不同的类型标识不同的错误)
我们可以设计一个简单的异常类型:
fig5
用异常类型区分不同的错误
如果程序中用到多个会抛出异常的函数,可以通过抛出的类型确定不同的处理过程:
fig6
fig7

86.异常(2)exception类

exception类
对于上一节中,用异常类型区分不同的错误,需要重复写catch,现在我们可以使用C++提供的标准类exception类,用作其他异常类的基类,其中有一个返回字符串的虚函数what(),用于返回出错的原因(利用了C++的多态性)

fig8
现在对于不同的异常类型,只需要一个catch就能调用不同的成员(利用了多态性),取决于try内部的操作抛出哪个异常类,但在catch中都是用基类去指向派生类。
fig9
bad_alloc异常类
对于异常类,除了exception基类,C++还有一个bad_alloc异常类:

  • 申请动态变量失败时,早期的C++返回一个空指针,现在的C++则是抛出bad_alloc异常类,bad_alloc从exception派生,提供了what()
    fig10

87.RTTI(1)

RTTI:运行阶段类型识别(Runtime Type Identification)

RTTI用途:
1.跟踪对象类型;
2.在继承结构中确定类型转换的安全性;

支持RTTI的元素
1.typeid运算符返回一个type_info类类型的值,type_info存储了有关特定类型的信息;
2.用dynamic_cast检查继承层次中基类指针或引用向派生类转换的合法性;

typeid运算符和type_info类
运算符typeid:获取对象的类型信息,是一元运算符
运算对象:类名 或 结果为对象的表达式
返回值:type_info对象的引用

type_info类:有一个成员函数name(),返回类或者对象对应的类名

示例
fig11

88.RTTI(2)

dynamic_cast运算符:用于检查是否可以安全将基类地址转换成派生类地址。
fig12
直接进行类型强制转换,编译器不会检查,会造成后期的内存读写错误,应该使用RTTI,如果返回空指针,对程序的后续行为执行才是安全的。

89.类型转换运算符

C语言风格的强制类型转换:(类型名) 表达式

比如:

int a=5;
char* p=(char*) &a;
int* pi=(int*) p;

C风格的强制类型转换缺点:没有检查或指明所做转换的意义。

C++严格规范转换限制,使得转换过程更加规范,并设置了4个类型转换运算符:

  • dynamic_cast:用于检查是否可以安全将基类地址转换成派生类地址。
  • const_cast
  • static_cast
  • reinterpret_cast

const_cast:删除对象的常量性质
fig13
输出结果为:
fig14
可以发现,其实const修饰的常量并没有被修改(因为常量在内存的不可变区域),const_cast的用途其实是:

  • 当调用了一个形式参数不是const的函数,但实际参数是const的,但是我们确定这个函数不会对参数做修改,因此需要const_cast去除实际参数的const限定,以便函数能够接受这个实际参数。

static_cast:编译器支持的隐式转换(自动类型转换)
比如:

double x=1.998;
int a;
a=static_cast<int> x;

可以看出,static_cast是安全的转换,只是会丢失精度;


C语言自动类型转换出现的场合
1.赋值或初始化时,如果右边的表达式计算结果类型与左边的变量类型不同:右边值被转换成左边变量类型;
2.函数参数传递时,实际参数被转换成形式参数的类型;
3.表达式中的运算数类型不一致,需要遵循转换规则:把精度小的运算数向精度大的运算数转换;


reinterpret_cast:危险的转换,重新解释地址中的内容
比如:
fig15
reinterpret_cast这种转换看起来是没有意义的(因为两个变量之间没有关联关系),这种转换更多用在输入输出场景(把内存中的一块空间内容完整写入一个文件中)

C++相比C,增加了类型转换运算符,一是为了让编译器检查类型转换的合理性,二是为了让读代码的程序员看到当前类型转换的意义。

90.string类

对于C风格字符串:
用字符数组存储
无法用运算符进行操作
执行字符串操作时需要特别注意空间问题

C++中专门处理字符串的类,在库string中,用动态数组存储(动态数组可以回顾20.数组的替代品中的vector,注意到另一个替代品array类可以回顾78.类模板(2)非类型参数),必要时会自动扩大空间
功能:

  • 不同的构造方法
  • 字符串赋值(=)
  • 字符串连接(+)
  • 字符串比较(>, <, >=, <=, ==, !=)
  • 字符串输入输出(>>, <<)
  • 用下标访问字符串的元素

示例:
fig16

91.智能指针

问题引入
fig17
上述函数存在内存泄漏的可能:当抛出异常时,局部变量ps的空间被释放,但ps指向的动态变量没有释放。

解决方案是使用智能指针;

智能指针:可以在释放指针本身的空间时候,调用它指向的对象的析构函数,从而析构该指针指向的对象

智能指针是一个类模板,模板参数是智能指针指向的对象类型。智能指针包含在库memory中。常用的智能指针有3种:

  • auto_ptr:C++98提出
  • unique_ptr:C++11提出
  • shared_ptr:C++11提出

智能指针示例
fig18
3种智能指针的区别:多个指针指向同一个对象时,3种指针有不同的行为

auto_ptr:在赋值时,会将右边指针的控制权转移给左边指针,右边的指针就失去了控制权(自动指向NULL),这种情况下,对右边指针进行读写操作会出错;

unique_ptr:明确指出不允许共享,当发生指针赋值时,编译出错;

shared_ptr:允许多个指针指向同一个对象,析构时,只有最后一个析构的指针会调用对象的析构函数;

auto_ptr示例
fig19
unique_ptr示例
fig20
shared_ptr示例
fig21


注意到85节中的抛出异常类throw bad_hmean(a, b);语句,bad_hmean是一个类类型;

91节智能指针中,出现auto_ptr<string> ps (new string("sentence"))auto_ptr<string> (new string("sentence"))这种语句;

这些类的实例化方式,可以回顾53.对象构造中的内容

  • throw bad_hmean(a, b);中的bad_hmean(a, b)是构造函数的显式调用
  • auto_ptr<string> ps (new string("sentence"))是构造函数的隐式调用(定义对象时自动调用);
  • auto_ptr<string> (new string("sentence"))是构造函数的显式调用


http://chatgpt.dhexx.cn/article/Enpnf2PK.shtml

相关文章

SAP Fiori学习笔记

资料链接&#xff1a;有些是需要自带梯子的哦&#xff5e; Fiori Design Guidelines​experience.sap.com戴团长&#xff1a;SAP Fiori Design​zhuanlan.zhihu.com如何评价 SAP Fiori Design Guidelines&#xff1f;​www.zhihu.comhttps://mp.weixin.qq.com/s?__bizMzIyNjY…

C++Prime Plus(2)

目录 21.for循环(1)22.for循环(2)23.while循环24.do while循环25.二维数组与嵌套循环26.if语句27.逻辑表达式28.条件表达式29.switch语句30.文件概念31.文本文件的输入输出32.函数详解(1)回顾33.函数详解(2)参数传递34.函数详解(3)数组传递35.函数详解(4)C风格字符串36.递归概念…

C++Prime Plus(1)

目录 1.C简介2.程序生成&#xff08;创建源码&#xff0c;编译和链接&#xff09;3.进入C4.C语句5.函数入门6.整型7.char&#xff0c;bool&#xff08;小整数&#xff09;8.const与符号常量9.浮点数10.算术表达式11.数组12.C风格字符串13.C风格字符串14.结构15.指针16.动态内存…

C++Prime Plus(7)

目录 96.输入输出概述97.使用cout输出(1)ostream基本功能98.使用cout输出(2)格式化输出99.使用cin输入100.文件(1)简单的文件IO101.文件打开的进一步讨论102.二进制文件访问103.随机读写 96.输入输出概述 C的输入输出是由库iostream中提供的一组类实现的&#xff1b; 流 C把输…

E-Prime软件包及安装

E-Prime软件包及安装 1 版本问题2 安装过程3 注意事项4 唠唠叨叨 Hello&#xff0c; 这里是行上行下&#xff0c;我是喵君姐姐~ 众所周知&#xff0c;E-Prime是实验设计的执行者。 当我们提出一个想法&#xff0c;则需要一个具体的软件来实现它。 而E-Prime相对于Matlab和Py…

Prime Sample

又发现了个框架 但没有代码啊~~ 还是搬来了&#xff0c;重要样本关注机制&#xff0c;一种新颖的目标检测框架 上论文 论文地址&#xff1a; https://arxiv.org/pdf/1904.04821.pdf 在目标检测框架中&#xff0c;平等对待所有样本并以平均性能最大化目标是一种常见的范例。在…

Prime Factors

此题需要使用到质因子分解的算法&#xff0c;可以参考以下链接&#xff1a; https://blog.csdn.net/qq_42410605/article/details/100150140 题目描述&#xff1a; Given any positive integer N,you are supposed to find all of prime factors,and write them in the form…

SpringBoot实现分布式锁

SpringBoot实现分布式锁 先了解一下线程数&#xff1a; 线程锁 线程锁&#xff1a;主要用来给类&#xff0c;方法&#xff0c;代码加锁&#xff0c;当某个方法或者某块代码使用synchronize关键字来修饰&#xff0c;那么在同一时刻最多只能有一个线程执行该代码&#xff0c;如…

深入理解ConcurrentHashMap原理分析以及线程安全性问题

在之前的文章提到ConcurrentHashMap是一个线程安全的&#xff0c;那么我么看一下ConcurrentHashMap如何进行操作的。 ConcurrentHashMap与HashTable区别&#xff1f; HashTable put()源代码 我们来看一下put 操作&#xff1a; 方法体 被 同步锁标记&#xff0c;由于同步锁的…

Redis分布式锁到底安全吗?

若有收获,请记得分享和转发哦 这篇文章我想和你聊一聊&#xff0c;关于 Redis 分布式锁的「安全性」问题。 Redis 分布式锁的话题&#xff0c;很多文章已经写烂了&#xff0c;我为什么还要写这篇文章呢&#xff1f; 因为我发现网上 99% 的文章&#xff0c;并没有把这个问题真正…

Java线程安全

前段时间有测试一个后端对账单和话单采集服务,在测试过程中有涉及到数据库读写逻辑和并发的场景,所以结合经验针对系统技术架构设计了部分并发场景结合数据库读写时可能出现的一些问题的用例,也确实出现了一些测试环境容易忽视,线上环境确确实实可能出现的问题,当然最后还是得到…

线程安全之 - ThreadLocal

ThreadLocal的底层原理 ThreadLocal是Java中所提供的线程本地存储机制&#xff08;线程内共享&#xff09;&#xff0c;可以利⽤该机制将数据缓存在某个线程内部&#xff0c; 该线程可以在任意时刻、任意⽅法中获取缓存的数据&#xff1b;ThreadLocal底层是通过ThreadLocalMap…

线程锁(ReentrantLock、synchronized)为何不能用作分布式锁

为什么使用分布式锁 分布式锁实现目前有三种&#xff1a; 数据库乐观锁&#xff1b;ZooKeeper的分布式锁;Redis的分布式锁&#xff1b; 在以前单体架构Web应用场景下&#xff0c;我们可以使用ReentrantLock或synchronized进行上锁&#xff0c;保证资源安全&#xff0c;现如今大…

Redis分布式锁真的安全吗?

大家好&#xff0c;今天我们来聊一聊Redis分布式锁。 首先大家可以先思考一个简单的问题&#xff0c;为什么要使用分布式锁&#xff1f;普通的jvm锁为什么不可以&#xff1f; 这个时候&#xff0c;大家肯定会吧啦吧啦想到一堆&#xff0c;例如java应用属于进程级&#xff0c;…

ThreadLocal能解决线程安全问题?胡扯!本文教你正确的使用姿势【享学Java】

跟对领导很重要&#xff1a;愿意教你的&#xff0c;并且放手让你做的领导要珍惜。 目录 前言正文ThreadLocal是什么&#xff1f;ThreadLocal怎么用&#xff1f;局限性InheritableThreadLocal向子线程传递数据开源框架使用示例 ThreadLocal不能解决共享变量的线程安全问题Thread…

Java线程安全详细总结

以下是我的PPT文档&#xff0c;不知道怎么复制到博客&#xff0c;只能一个一个插入图片发上来了。感觉总结的不错&#xff0c;分享一下。 文档地址&#xff1a;http://download.csdn.net/detail/csujiangyu/9526641

分布式系统详解--基础知识(线程)

分布式系统详解--基础知识&#xff08;线程&#xff09; 一、导读 前面跟大家讲了一下 分布式系统详解--基础知识&#xff08;概论&#xff09; &#xff0c;可以稍微了解一下大体上分布式是怎么一回事了。这片篇文章主要是讲述一下线程的问题分别介绍一下&#xff0c;什么线…

分布式项目线程安全问题(电商扣减库存的安全问题1)

电商减库存存在的安全问题 Override public void deductStock(Map<Long, Integer> skuMap) {for (Map.Entry<Long, Integer> entry : skuMap.entrySet()) {Long skuId entry.getKey();Integer num entry.getValue();// 查询skuSku sku getById(skuId);// 判断…

分布式项目中 如何保证线程安全问题?-------ZooKeeper

前沿&#xff1a; 上篇文章我们聊到了在解决分布式项目中线程安全问题&#xff0c;提到解决方案还有其他的&#xff0c;那么在此提出 基于 zookeeper 解决分布式项目中的线程安全问题 也是目前市面上比较流行的。做为一个高级开发工程师也是必须要学习的。 ZooKeeper是什么东…

分布式线程安全(redis、zookeeper、数据库)

https://blog.csdn.net/u010963948/article/details/79006572 Q:一个业务服务器&#xff0c;一个数据库&#xff0c;操作&#xff1a;查询用户当前余额&#xff0c;扣除当前余额的3%作为手续费 synchronized lock db lock Q&#xff1a;两个业务服务器&#xff0c;一个数据库&…