C++笔记-模板初阶,string(上)
一.模板初阶
1.泛型编程

以往我们要交换不同类型的两个数据就要写不同类型的交换函数,这是使用函数重载虽然可以实现,但是有以下几个不好的地方:
1.重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数。
2.代码的可维护性比较低,一个出错可能导致所有的重载均出错。
此时就引出了模板这个概念,就是告诉编译器一个模子,让编译器根据不同类型利用该模子来生成代码。
泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。
2.函数模板
2.1函数模板概念
函数模板代表了一个函数家族,该函数与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。
2.2函数模板格式
template<typename T1,typename T2...typename Tn>
返回值类型 函数名(参数列表){}


这样就完成了一个简单的交换函数模板,其中的typename可以换成class,不影响使用。
2.3函数模板的原理
函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具,所以其实模板就是将本来我们做的重复的事情交给了编译器。

在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。
2.4函数模板的实例化
用不同类型的函数使用函数模板时,成为函数模板的实例化。模板参数实例化分为:隐式实例化和显式实例化。


此时就可以使用隐式实例化,但是在实例化中会遇到其他特别的情况:

比如这样,传过去的参数类型不同,编译器就会不知道到底返回什么类型,就会报错。
这时就需要用到显式实例化。


显式实例化就是在函数名后面用<指定类型>就是指定当前这个函数的返回值是什么类型。
再比如:

参数中T并没有作为参数,此时单独调用这个函数就会报错,就不知道T的类型是什么。
可能有人会说用一个变量来接收函数返回值不就行了,那我要就不接受呢?
此时也是必须用显式实例化的:

2.5模板参数的匹配原则
1.一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数

如上面这种情况,如果有一个专门处理int类型的加法函数和一个加法函数模板,此时调用加法函数会调用哪个呢?
此时就会遵从有现成的用现成的,也就是会调用专门处理int类型的加法函数。

经过调试也可以发现调用的是现成的加法函数。
2.对于非模板函数和同名函数模板,如果其他条件都相同,在调用时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数,那么将选择模板。
后半句话用下面这个例子来解释:

如果我们传不同的参数,此时就会报错,其实就是因为编译器现在要调用模板,但是参数不同,所以才报错。


此时用显式实例化就可以解决问题。
3.函数模板不允许自动类型转换,但普通函数可以进行自动类型转换
3.类模板
3.1类模板的定义格式
template<class T1,class T2...class Tn>
class 类模板名
{
//类内成员定义
};
3.2类模板的实例化

拿之前学过的Stack类举例,在这个例子中可能有人会觉得为什么非得用模板,直接用typedef不就行了吗?
如果只用一个Stack,那确实不需要用模板,但如果我的程序需要两个Stack呢,并且两个Stack的类型不一样,此时用typedef就解决不了这个问题,此时就需要用到模板。

此时就用创建了一个类模板,但为什么下面实例化会出错呢?
答案是因为类模板不能根据构造函数来推导出T的类型。
所以类模板基本都是显式实例化:

这样才能确定T的类型。

如果要做声明与定义分离,是需要重新写一个模板的,上面那个模板只是Stack类的,下面要再用的话需要重新写一个。
另外类模板不支持声明和定义在不同的文件中,会报链接错误。
二.string类
1.为什么要学string类?
C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C++标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合0OP的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。
2.标准库中的sring类
在使用string类时,必须包含string头文件和using namespace std;
2.1string的构造函数
string底层其实就是一个char类型的顺序表,就是一个数组。
![]()
第一种构造的方式就是可以创建一个空字符串。
![]()
第二种就是在括号内直接接收一个字符串进行初始化。
![]()
当然也可以以这种方式进行初始化。
![]()
如果使用引用的话这样写是不行的,因为这种方式其实就相当于单参数隐式类型转换,而类型转换就会产生临时对象,临时对象具有常性,不能被修改,而引用会导致权限被放大,使其能够被修改,所以此时程序会报错。

此时加上const就可以解决问题,因为加上const后权限就相等了。
![]()
上面这种方式是最能体现string类底层是数组的,把10个*放入其中进行初始化,这种方式也是支持的。
还有几种不怎么常用的构造函数:


这种方法中有三个参数,第一个就是你要指定的字符串,第二个参数就是从哪个位置开始,而最后一个参数就是从上一个参数位置开始需要几个字符。
用上面的例子来实现结果就如第二幅图,把s2第六个位置后面的三个字符初始化给s6。
注意:
1.第三个参数不写的话是有默认值的,这个默认值如果去查的话显示是-1,但其实就是整数的最大值。如果不写第三个参数,就默认从第二个参数的位置开始,把后面所有的字符初始化给新字符串。
2.如果给了第三个参数,但是长度大于原字符串,那么效果和第一条是一样的。


还有一种是如上图这样初始化,这个方法有两个参数,第一个参数就是字符串,第二个参数是一个整型,意思是获取第一个参数的前n个字符。
实现效果就如第二幅图所示,获取了前5个字符,也就是hello。
2.2string的析构函数
string是一个类,那么就会有自己的析构函数,而析构函数不需要我们手动调用,编译器会自动调用,所以析构函数不需要怎么关注,编译器就会自动调用析构函数把类中的资源给释放掉。
2.3string的=运算符重载


string类也是支持=运算符重载的,基本应用就是上面所示。
2.4string的遍历
string的遍历这里讲三种方式:
2.4.1operator[]遍历


string类中是有[]符号重载的,这样我们就可以像数组一样来遍历字符串中的每个字符。
如上图所示,我们可以对第一个字符进行++或者将其更换为另一个字符,这些操作都是可以的。


或者也可以像这样遍历字符串的每一个字符并将其打印出来,也是可以的。
注意:字符串的size()函数得到的是字符的数量,并不包含\0。
![]()

如上图,得到的字符数量是11,只是字符的数量。
另外,如果要访问的字符超出了字符串的长度,程序运行后会报错。
![]()

这其实就是在[]符号重载中加入了assert断言,如果访问的字符超出了字符串的长度,就会报上面的错误。
2.4.2迭代器遍历


迭代器便的基本用法就如上图所示。
其中的iterator是string类中的一个类型,而begin获得的是字符串的第一个位置,end获得的是字符串最后一个位置的下一个位置,在这里it其实就相当于指针,通过解引用来获取每个字符。
注意:迭代器不一定是指针,只是在这里是指针而已,不要认为迭代器就是指针。
迭代器不只是能读字符串而已,也是能对字符串进行修改的:


如上图所示,我们通过解引用也是能够对字符串进行修改的。
这里可能有人可能会有疑惑,为什么要学迭代器来遍历字符串呢?直接用[]符号重载来遍历不是更好理解吗?
在当前这个例子中呢确实是这样,但是迭代器是容器的通用访问方式,后面还有其他的容器,有的容器底层并不是数组,而是链表呢?
这时就不能用[]符号重载来进行访问,就只能用迭代器进行访问,所以说迭代器是必须要掌握的。
2.4.3范围for遍历
在讲范围for之前我们先了解一下auto这个东西。


auto这个类型基本应用如上图所示,它的作用就是可以自动通过右边初始化值来推导k的类型。
有人可能会有疑惑,这样写有什么意义吗?我直接写具体类型不行吗?
在这里用auto确实没社么意义,但在我们上面的例子中我们再来看看:


在上面的例子中,我们要写it的类型要写比较长的一串,此时我们就可以利用auto来代替,前面那么长的一串直接用auto来代替,这样代码量就减少并且代码看着也更简洁了,这其实才是auto常用的地方。



auto也是可以做返回值和参数类型的,不过用这两种方式时要谨慎使用,这里还体现的不明显,如果有很多函数相互调用,一旦出问题,你想找到参数什么类型就会很麻烦。
下面来讲范围for的用法:


范围for的基本格式如上图所示,其中e是可以取其他名字的,这个不唯一,我用e来演示。
范围for其实就是自动取出容器中的数据给对象,并且自动结束。
范围for不仅可以读取数据,也是可以对容器内的数据进行修改的:


如果要修改容器中的数据,我们要使用引用,因为范围for只是把容器中的数据赋值给e,相当于形参,而形参修改时不会影响实参的,所以我们要修改的话用引用。

auto也可以换成具体的类型,不过一般在使用范围for时都用auto。
当然,容器也可以是一个整型数组:


这些操作都是可以实现的。
范围for原理:在编译时会传化成迭代器来使用
以上就是模板初姐和string(上)的内容。
相关文章:
C++笔记-模板初阶,string(上)
一.模板初阶 1.泛型编程 以往我们要交换不同类型的两个数据就要写不同类型的交换函数,这是使用函数重载虽然可以实现,但是有以下几个不好的地方: 1.重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时&a…...
关于cmd中出现无法识别某某指令的问题
今天来解决以下这个比较常见的问题,安装各种软件都可能会发生,一般是安装时没勾选注册环境变量,导致cmd无法识别该指令。例如mysql,git等,一般初学者可能不太清楚。 解决这类问题最主要的是了解环境变量的概念&#x…...
绿联NAS安装内网穿透实现无公网IP也能用手机平板远程访问经验分享
文章目录 前言1. 开启ssh服务2. ssh连接3. 安装cpolar内网穿透4. 配置绿联NAS公网地址 前言 大家好,今天给大家带来一个超级炫酷的技能——如何在绿联NAS上快速安装cpolar内网穿透工具。想象一下,即使没有公网IP,你也能随时随地远程访问自己…...
d9-326
目录 一、添加逗号 二、爬楼梯 三、扑克牌顺子 添加逗号_牛客题霸_牛客网 (nowcoder.com) 一、添加逗号 没啥注意读题就是 注意逗号是从后往前加,第一位如果是3的倍数不需要加逗号,备注里面才是需要看的 count计数 是三的倍数就加逗号,…...
汇编(六)——汇编语言程序格式及MASM
汇编语言的实现也是先利用某种编辑器编写汇编语言源程序(*.ASM),然后经过汇编得到目标模块文件(*.OBJ)、连接后形成可执行文件(*.EXE)。 1、汇编语言程序的语句格式 汇编语源程序由语句序列构成…...
Win11+VS2022+CGAL5.6配置
1. CGAL库简介 CGAL(Computational Geometry Algorithms Library)是一个开源的计算几何算法库,主要用于处理几何问题和相关算法的实现。它提供了丰富的几何数据结构和高效算法,覆盖点、线、多边形、曲面等基本几何对象的表示与操…...
【Linux】MAC帧
目录 一、MAC帧 (一)IP地址和MAC地址 (二)MAC帧格式 (三)MTU对IP协议的影响、 (四)MTU对UDP协议的影响 (五)MTU对TCP协议的影响 二、以太网协议 &…...
Codeforces Round 1013 (Div. 3)(A-F)
题目链接:Dashboard - Codeforces Round 1013 (Div. 3) - Codeforces A. Olympiad Date 思路 找到第一个位置能凑齐01032025的位置 代码 void solve(){int n;cin>>n;vi a(n10);int id0;map<int,int> mp;for(int i1;i<n;i){cin>>a[i];mp[a…...
Flink 常用及优化参数
流批模式 SET execution.runtime-mode streaming; // or batch基础 Checkpoint 配置 -- 启用 Checkpoint,间隔 5 分钟 SET execution.checkpointing.interval 5min; -- Checkpoint 超时时间(10 分钟) SET execution.checkpointing.timeou…...
Vite 与 Nuxt 深度对比分析
一、核心定位差异 二、核心功能对比 渲染能力 Vite:默认仅支持客户端渲染(CSR),需通过插件(如vite-plugin-ssr)实现 SSR/SSG,但配置灵活 Nuxt:原生支持 SSR(服务端渲…...
Linux内核 内存管理 物理内存初始化流程
1.ARM64页表初始化流程图 start_kernel()│▼ setup_arch() // 架构相关初始化│▼ early_fixmap_init() // 初始化Fixmap(临时映射设备树等)│▼ arm64_memblock_init() // 从设备树解析内存布局│▼ arm…...
PyBluez2 的详细介绍、安装指南、使用方法及配置说明
PyBluez2:Python 蓝牙开发的核心库 一、PyBluez2 简介 PyBluez2 是 Python 的开源蓝牙编程库,支持蓝牙 2.0、BLE(低功耗蓝牙)和传统蓝牙协议栈的开发。它提供了对蓝牙硬件适配器的底层控制,适用于设备发现、配对、数…...
通过一个led点灯的demo来熟悉openharmony驱动编写的过程(附带hdf详细调用过程)
概述 本应用程序(led_rgb)是在上实现直接通过消息机制与内核驱动进行交互,设置RGB三色灯的亮灯行为。我从网上随便找了个demo测试了一下,坑了三天…,整个状态如下图,同时也迫使我深度梳理了一下整个流程框架。直到绝望的时候&…...
pycharm2024.1.1版本_jihuo
目录 前置: 步骤: step one 下载软件 step two 卸载旧版本 1 卸载软件 2 清除残余 step three 下载补丁 step four 安装2024.1.1版本软件 step five 安装补丁 1 找位置放补丁 2 自动设置环境变量 step six 输入jihuo码 前置: 之…...
目标检测20年(四)——最终章
欢迎各位读者尽情阅读前三篇文献解读。这一篇将会介绍文献的第五部分:目标检测近些年的新技术发展以及第六部分:总结与未来展望。这也是本篇论文解读的最后一篇文章。 目录 五、目标检测最新进展 5.1 不采用滑动窗口的检测 5.2 旋转和尺度变化的鲁棒性…...
PyTorch处理数据--Dataset和DataLoader
在 PyTorch 中,Dataset 和 DataLoader 是处理数据的核心工具。它们的作用是将数据高效地加载到模型中,支持批量处理、多线程加速和数据增强等功能。 一、Dataset:数据集的抽象 Dataset 是一个抽象类,用于表示数据集的接口。你…...
【Linux】POSIX信号量与基于环形队列的生产消费者模型
目录 一、POSIX信号量: 接口: 二、基于环形队列的生产消费者模型 环形队列: 单生产单消费实现代码: RingQueue.hpp: main.cc: 多生产多消费实现代码: RingQueue.hpp: main.…...
Spring Boot 连接 MySQL 配置参数详解
Spring Boot 连接 MySQL 配置参数详解 前言参数及含义常用参数及讲解和示例useUnicode 参数说明: 完整配置示例注意事项 前言 在 Spring Boot 中使用 Druid 连接池配置 MySQL 数据库连接时,URL 中 ? 后面的参数用于指定连接的各种属性。以下是常见参数…...
[linux] linux基本指令 + shell + 文件权限
目录 1. Linux的认识 1.1. Linux的应用场景 1.2. Linux的版本问题 1.3. 操作系统的认识 1.4. 常用快捷键 2. 常用指令介绍 2.1. ADD 2.1.1. touch [file] 2.1.1.1. 文件的属性信息 2.1.2. mkdir [directory] 2.1.3. cp [file/directory] 2.1.4. echo [file] 2.1.4.…...
查看进程文件描述符的限制
查看进程文件描述符限制 rootgb:/home/gb/Monitor-Device-Mgr/Monitor-Device-Mgr/bin# ps -ef |grep Monitor-Device-Mgr root 3976 2380 59 11:10 pts/2 00:00:06 ./Monitor-Device-Mgr root 4010 2395 0 11:10 pts/3 00:00:00 grep --colorauto Monito…...
Python实现小红书app版爬虫
简介:由于数据需求的日益增大,小红书网页版已经不能满足我们日常工作的需求,为此,小编特地开发了小红书手机版算法,方便大家获取更多的数据,提升工作效率。 手机版接口主要包括:搜素࿰…...
【docker】docker-compose安装RabbitMQ
docker-compose安装RabbitMQ 1、配置docker-compose.yml文件(docker容器里面的目录请勿修改)2、启动mq3、访问mq4、查看服务器映射目录5、踩坑5.1、权限不足 1、配置docker-compose.yml文件(docker容器里面的目录请勿修改) versi…...
playwright-go实战:自动化登录测试
1.新建项目 打开Goland新建项目playwright-go-demo 项目初始化完成后打开终端输入命令: #安装项目依赖 go get -u github.com/playwright-community/playwright-go #安装浏览器 go run github.com/playwright-community/playwright-go/cmd/playwrightlatest insta…...
LeetCode hot 100 每日一题(13)——73. 矩阵置零
这是一道难度为中等的题目,让我们来看看题目描述: 给定一个 _m_ x _n_ 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 提示: m matrix.lengthn matrix[0].length1 < m, n …...
CEF 给交互函数, 添加控制台是否显示交互参数log开关
CEF 控制台添加一函数,枚举 注册的供前端使用的CPP交互函数有哪些 CEF 多进程模式时,注入函数,获得交互信息-CSDN博客 这两篇文章,介绍了注入函数,在控制台中显示 各自提供的交互函数信息。 有些场景下,我们还需要更详细的信息,比如想知道 彼此传递的参数, 如果每次调…...
云端存储新纪元:SAN架构驱动的智能网盘解决方案
一、企业存储的"不可能三角"破局 1.1 传统存储架构的困局 性能瓶颈:NAS架构在1000并发访问时延迟飙升300%容量限制:传统RAID扩容需停机维护,PB级存储扩展耗时超48小时成本矛盾:全闪存阵列每TB成本高达$3000࿰…...
PVE 安装黑苹果 MacOS
背景 我需要一台黑苹果,登录我不常用苹果账号。 方法 The Definitive Guide to Running MacOS in ProxmoxRunning a MacOS 15 Sequoia VM in ProxMox VE及视频 按照第二个的视频一步一步配置,第一个链接提供了不同版本OS...
Unity URP自定义Shader支持RenderLayer
前言: 当我们想用一个灯光只对特定的物体造成影响,而不对其余物体造成影响时,我们就需要设置相对应的LightLayer,但是这在URP12.0是存在的,在之后就不存在LightLayer这一功能,URP将其隐藏而改成了RenderLa…...
Axure项目实战:智慧城市APP(完整交互汇总版)
亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢! 课程主题:智慧城市APP 主要内容:主功能(社保查询、医疗信息、公交查询等)、活动、消息、我的页面汇总 应用场景ÿ…...
LVS-DR模式配置脚本
LVS-DR模式配置脚本 实验环境,需要4台虚拟机 IP说明172.25.254.101客户端172.25.254.102负载均衡器DS172.25.254.103真实服务器RS172.25.254.104真实服务器RSVIP:172.25.254.255/32 系统必须有ipvsadm和ifconfig命令 dnf install ipvsadm dnf install n…...
