模板初阶和string容器

目录

1.模板

函数模板

函数模板的调用规则:

类模板 

 容器与迭代器

string的简单介绍

iterator(迭代器)

begin()与end()

rbegin()和rend()

 Capacity(容量)

shrink_to_fit()

Element access(获取字符串中的元素)

Modifiers(修改字符串)

String opertations 

其他 


1.模板

什么是模板?模板能有什么用?

比如,你想写一个函数处理一些不同类型的数据,虽然数据的类型不同,但函数中处理数据的方法是一致的。如果不应用模板,那么就需要根据处理的数据类型写相应的仅仅只是参数类型不同的函数。

可以通过模板来实现泛式编程,大大减少程序中冗余的代码。

函数模板

例子:

int add(int a, int b)
{
	return a + b;
}

double add(double a, double b)
{
	return a + b;
}

int main()
{
	int a = 1;
	int b = 2;
	double c = 2.1;
	double d = 2.3;
	add(a, b);
	add(c, d);
	return 0;
}

向要实现数据的加减,但加减的数据的类型多种多样需要写处理相应数据类型的函数,代码很容易冗余。

这是后就需要使用模板,

template<class T>
T add(T a, T b)
{
	return a + b;
}

template是关键字,说明下面你写的一段代码是个模板

T是模板参数,如果你调用该函数时传的是int类型的数据,那么编译器会将T推导出来为int,并生成相应的参数为int,返回值为int的函数。

template<class T>
T add(T a, T b)
{
	cout << sizeof(T) << endl;
	return a + b;
}

int main()
{
	int a = 1;
	int b = 2;
	double c = 2.1;
	double d = 2.3;
	add(a, b);
	add(c, d);
	return 0;
}

多模板参数

template<class T1,class T2>
//.......

函数模板的调用规则:

1.如果要处理的数据类型已经有实现的函数,那么就不会使用模板

int add(int a, int b)
{
	cout << "已存在的处理int" << endl;
	return a + b;
}

double add(double a, double b)
{
	cout << "已存在的处理double" << endl;
	return a + b;
}

template<class T>
T add(T a, T b)
{
	cout << "模板函数" << endl;
	return a + b;
}

int main()
{
	int a = 1;
	int b = 2;
	double c = 2.1;
	double d = 2.3;
	add(a, b);
	add(c, d);
	return 0;
}

2. 如果没有现成的函数就使用模板生成一个该类型的模板

	float e = 1.1;
	float f = 1.2;
	add(e, f);

3.如果传的参数无论是与已有函数还是模板参数(表面上(只看数据类型不考虑隐式类型转换))都不匹配,那么就可能报一些错误无法正常运行。

	add(a, c);//传一个int,和一个double

如果调用的是已存在的函数,可能存在调用歧义的问题,以上的代码就有这个问题,因为我们实现了一个处理int的函数,一个处理double的函数。并且传的参数一个是int一个是double,如果将double强转为int那么就调用int函数,如果将int强转为double那么就调用double的函数,但不幸的是编译器无法确定强转的顺序的先后,所以有调用歧义,不能运行。

如果调用的是模板呢?

跟上面的解释差不多,无法确定是将int强转为double还是将int强转为double,所以模板无法推导出模板参数T的类型

解决方法:

就是确定对那个数据进行强制类型转换

	add(a, (int)c);//将double强转为int
	add((double) a, c);//将int强转为double

类模板 

template<class T>
class A
{
private:
	T _a;
};
A<int> a;//用int模板实例化
A<double> b;//用double模板实例化

类模板如何实例化出相应的对象的?

类模板会生成相应的类,在通过类的构造函数初始化对象

 容器与迭代器

什么容器?什么又是迭代器?两者之间有什么关系?

容器(container):简单来说就是跟所学的数据结构一样,就是用来存储数据的。比如,顺序表,链表,堆等等。

迭代器(iterator):就是访问数据的工具

关系:迭代器可以用同一种方法来访问不同容器中的数据。

迭代器就是一个类似于指针的东西。

迭代器的底层也是一个类,但string和vector容器的iterator可能是指针。

迭代器的取值范围是左闭右开

迭代器的使用

	string s = "hello world";
	
	for (string::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it;
	}

这个现在不懂没关系,下面会讲到。

string的简单介绍

链接:可以看更详细的使用说明

string - C++ Reference (cplusplus.com)

string是字符串类型

string的底层是一个类。

string姑且算一种容器吧,在C语言中没有string类型,但又字符数组就跟string差不多。

iterator(迭代器)

begin()与end()

begin返回string的起始迭代器

end返回string的结尾的迭代器

可以把返回值理解成类似于指针的东西。

使用:

int main()
{
	string s = "hello world";
	//第一种遍历一遍字符串
	for (string::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it;
	}
	cout << endl;
	//第二种遍历方式
	string::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it;
		it++;
	}
	cout << endl;
	//第三种遍历(范围for)
	for (auto e : s)
	{
		cout << e;
	}
	return 0;
}

rbegin()和rend()

与begin()和end()不同的是rbegin()和rend(),返回值的类型不同,为反向迭代器reverse_iterator,

rbegin(),rend()begin(),end()
返回值类型reverse_iterator(反向迭代器)iterator
遍历方式从后往前遍历从前往后遍历

 Capacity(容量)

size():返回字符串的大小

length():跟size()的功能一样

capacity():返回容器的大小

max_size():返回能开辟的最大字符串的大小

resize()

改变字符串的size ,但如果想要改变后的大小大于容器的容量,那么就会先扩容,在改变字符的大小。

reserve()

可以扩容,但扩容只能往大的方向扩,如果你想扩容的大小小于等于原本容器的容量,那么就不会扩容。

 vs下的扩容:

	string s;
	int oldcapacity = s.capacity();
	cout << oldcapacity << endl;
	for (int i = 0; i < 1000; i++)
	{
		s.push_back('a');
		int newcapacity = s.capacity();
		if (newcapacity != oldcapacity)
		{
			oldcapacity = newcapacity;
			cout << newcapacity << endl;
		}
	}

 

由上图的代码和结果可知,容器的初始大小为15,之后差不多就是 1.5倍扩容。

 

clear()

将字符串变为一个空串(“”),但不改变容器的大小

empty()

判断该字符串是否是空串。

shrink_to_fit()

可以缩容,将容器缩小到适合字符串的大小可以减少不必要的空间浪费。

使用:

	string s = "hello world";
	cout << s.size() << endl;
	cout << s.length() << endl;
	cout << s.capacity() << endl;
	cout << s.max_size() << endl;
    //扩容
	s.reserve(100);
	cout << s.capacity() << endl;
	s.resize(20);
	cout << s.size() << endl;
    //清理字符串中的内容
	s.clear();
	cout << s << endl;
    //判空
	cout << s.empty() << endl;
	cout << s.capacity() << endl;
    //缩容
	s.shrink_to_fit();
	cout << s.capacity() << endl;

Element access(获取字符串中的元素)

operator[ ]:可以像数组一样通过[ ]访问字符串中的元素。

	string s("hello world");
	for (int i = 0; i < s.size(); i++)
	{
		cout << s[i];
	}
	cout << endl;

at:获得指定位置的元素。

front:获得第一个元素。

back:获得最后一个元素。

Modifiers(修改字符串)

operator+= 

 在字符串之后追加字符串

	string s;
	s += "hello world";
	string s1 = "aaaa";
	s += s1;
	s += 'b';

append

在字符串之后追加字符串

append没有重载的+=好用 

第六个是模板,传的参数是迭代器。

assign :赋值

push_back

在字符串最后追加字符

	string s;
	s += "hello world";
	s.push_back('a');

insert:向指定位置的字符串中插入数据

erase:删除指定位置的字符

	string s("hello world");
	string::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it;
		s.erase(it);
	}

 

因为string的删除是,将指定位置后的字符都向前移动一位,所以不存在迭代器失效的问题。

replace:替换掉stringzhong指定的一段字符串

swap:交换两个字符串,这里的交换明面上交换的是字符串,实际上也交换了字符串的大小和容器的容量 

pop_back:删除字符串最后的元素。

String opertations 

c_str:返回字符串的首地址 

copy: 将字符串中的数据从pos位置开始拷贝len个字符进s指向的数组中。

 find:在字符串中找s指向的内容,并返回存在相应的位置。如果字符串中没有相应的内容,就返回 string::npos.

 

 string::npos 就是string类中的一个静态变量,因为是size_t 所以初始化为-1,npos的只就是size_t的最大值。

返回npos的意思就是找到字符串末尾也没找到相应的内容。

rfind:相较于find,rfing就是从后往前找。

find_first_of:找到第一个字符既在字符串中出现,又在s指向的内容中。

find_last_of:相较于find_first_of,其从后往前找

find_first_not_of:从字符串中,找第一个在不在s指向的内容中出现的字符,

find_last_not_of:从后往前找

substr:返回字符串中,从pos位置开始len长度的字符串。

compare:比较两或某段字符串的 大小

其他 

operator+:将左右字符串相加并返回一个新字符串(相加的结果)

lhs: left hand side(左操作数)

rhs:right hans side(右操作数)

 relational operators:两个字符串之间的关系运算。

swap(std中):这个std的swap会在交换前会发生字符串的拷贝,浪费性能。

void swap(string& x, string& y)
{
	string tmp = x;//tmp会拷贝构造
	x = y;
	y = x;
}

而string类中定义的swap不需要定义一个临时变量,直接就可以交换,效率更高。

重载的operator>> 和 operator<< 可以使流插入和流提取的对象直接为string类,跟方便使用。

getline可以从键盘中读入的字符插入字符串中 ,这里空格也可以读取,但operator>>不可以读取空格。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Alibaba Cloud Toolkit前端使用proxy代理配置

1、vscode 先安装插件 Alibaba Cloud Toolkit 2、前端代码: /personnel: {// target: http://xxx.xx.xxx.xx:9100, // 测试环境// target: http://xxx.xx.xxx.xx:9200, // 线上环境target: http://127.0.0.1:18002, // toolkit 代理changeOrigin: true

如何取消闪迪Micro SD卡的写保护?这个技巧很有效!

由于受写保护影响&#xff0c;无法格式化闪迪Micro SD卡&#xff1f;别担心&#xff01;通过本文你可以学习如何解除闪迪Micro SD卡的写保护。 我的闪迪SD卡有写保护怎么办&#xff1f; “我打算格式化我的闪迪SD卡。但当我进行格式化时&#xff0c;提示我磁盘被写保护。我想用…

机器人具身智能Embodied AI

强调智能体&#xff08;如机器人&#xff09;通过物理身体在物理世界中的实时感知、交互和学习来执行任务。 通过物理交互来完成任务的智能系统。它由“本体”&#xff08;即物理身体&#xff09;和“智能体”&#xff08;即智能核心&#xff09;耦合而成&#xff0c;能够在复…

MaxKB开源知识库问答系统发布v1.3.0版本,新增强大的工作流引擎

2024年4月12日&#xff0c;1Panel开源项目组正式发布官方开源子项目——MaxKB开源知识库问答系统&#xff08;github.com/1Panel-dev/MaxKB&#xff09;。MaxKB开源项目发布后迅速获得了社区用户的认可&#xff0c;成功登顶GitHub Trending趋势榜主榜。 截至2024年7月4日&…

Git 安装

目录 Git 安装 Git 安装 在使用 Git 前我们需要先安装 Git。Git 目前支持 Linux/Unix、Solaris、Mac 和 Windows 平台上运行。Git 各平台安装包下载地址为&#xff1a;http://git-scm.com/downloads 在 Linux 平台上安装&#xff08;包管理工具安装&#xff09; 首先&#xff0…

基于Spring Boot框架的EAM系统设计与实现

摘 要&#xff1a;文章设计并实现一个基于Spring Boot框架的EAM系统&#xff0c;以应对传统人工管理模式存在的低效与信息管理难题。系统利用Java语言、JSP技术、MySQL数据库等技术栈&#xff0c;构建了一个B/S架构的高效管理平台&#xff0c;提升了资产管理的信息化水平。该系…

固态继电器的未来浅析

固态继电器(SSR)已成为传统机电继电器的可靠替代品&#xff0c;具有开关速度更快、使用寿命更长、电磁干扰更少等诸多优势。随着技术的不断进步&#xff0c;SSR的未来有望在设计和应用的各个方面实现更显著的改进和创新。 1.小型化和集成化&#xff1a; 固态继电器开发的主要趋…

当火热的Mamba遇到火热的YOLO,会发生怎么样的反应吗?

作者&#xff1a;浙江师范大学 论文地址&#xff1a;https://arxiv.org/pdf/2406.05835 代码地址&#xff1a;https://github.com/HZAI-ZJNU/Mamba-YOLO 目录 前言一、摘要二、介绍二、相关工作2.1 实时目标检测器2.2 端到端的目标检测器2.3 视觉状态空间模型 三 方法3.1 基础知…

服务器数据恢复—DS5300存储raid5阵列数据恢复案例

服务器存储数据恢复环境&#xff1a; 某单位一台某品牌DS5300存储&#xff0c;1个机头4个扩展柜&#xff0c;50块硬盘组建2组RAID5磁盘阵列&#xff08;一组raid5阵列有27块成员盘&#xff0c;存放Oracle数据库文件&#xff1b;另外一组raid5阵列有23块成员盘&#xff09;。存储…

OpenCV 车牌检测

OpenCV 车牌检测 级联分类器算法流程车牌检测相关链接 级联分类器 假设我们需要识别汽车图像中车牌的位置&#xff0c;利用深度学习目标检测技术可以采取基于锚框的模型&#xff0c;但这需要在大量图像上训练模型。 但是&#xff0c;级联分类器可以作为预训练文件直接使用&…

python通过COM Interface控制CANoe

python通过COM Interface控制CANoe 介绍打开示例工程python代码示例介绍 通过python可以控制CANoe的启动和停止等其他操作,在做高阶的自动化项目时可以用到。 打开示例工程 python代码示例 # --------------------------------------------------------------------------…

C++ 类和对象 构造函数

一 类的6个默认成员函数&#xff1a; 如果一个类中什么成员都没有&#xff0c;简称为空类。 例&#xff1a; #include <iostream> class Empty {// 空类&#xff0c;什么成员都没有 }; 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&a…

ONNX Runtime入门示例:在C#中使用ResNet50v2进行图像识别

ONNX Runtime简介 ONNX Runtime 是一个跨平台的推理和训练机器学习加速器。ONNX 运行时推理可以实现更快的客户体验和更低的成本&#xff0c;支持来自深度学习框架&#xff08;如 PyTorch 和 TensorFlow/Keras&#xff09;以及经典机器学习库&#xff08;如 scikit-learn、Lig…

文件打开的系统错误分析流程

当用户出现“Open file failed”错误时&#xff0c;手动产生dump文件。 &#xff08;1&#xff09;打开资源管理器&#xff0c;选择AppNameXXX.exe进程&#xff0c;右击鼠标选择“创建转储文件” (2) 生成转储文件 3.获取用户转储文件 4.用Visual studio2015打开dump文件分析…

深入讲解C++基础知识(二)

目录 一、复合类型1.引用1.1 引用的定义和使用1.2 引用的注意事项 2. 指针2.1 指针的定义和使用2.2 指针的四种状态2.3 指针的注意事项2.4 其他指针操作2.5 void* 指针 3. 理解复合类型变量的声明4. const 限定符4.1 const 对象的注意事项4.2 const 和引用4.2.1 术语&#xff1…

绘唐科技聚星文社是同款一键生成工具

聚星文社是同款一键生成工具 工具下载 绘唐科技成立于2015年&#xff0c;是一家专注于虚拟现实&#xff08;VR&#xff09;技术和产品开发的高科技企业。绘唐科技的目标是利用虚拟现实技术为人们带来更加沉浸式的体验&#xff0c;推动虚拟现实在各个领域的应用和发展。 绘唐科…

【FFmpeg】avcodec_send_frame函数

目录 1.avcodec_send_frame1.1 将输入的frame存入内部buffer&#xff08;encode_send_frame_internal&#xff09;1.1.1 frame的引用函数&#xff08;av_frame_ref &#xff09;1.1.1.1 帧属性的拷贝&#xff08;frame_copy_props&#xff09;1.1.1.2 buffer的引用函数&#xf…

学会python——用python制作一个绘图板(python实例十九)

目录 1.认识Python 2.环境与工具 2.1 python环境 2.2 Visual Studio Code编译 3.制作一个绘图板 3.1 代码构思 3.2 代码实例 3.3 运行结果 4.总结 1.认识Python Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的可…

Node.js实现一个文章生成器

前言 本文将从零开始&#xff0c;讲解如何使用Node.js来实现一个文章生成器 node里面有很多优秀的模块&#xff0c;现在我们就借助node的fs模块来操控文本&#xff0c;来实现我们想要的效果 效果展示 体验 fs 首先我们先创建一个json文件 里面放一些内容 接下来我们书写代码…

【博士每天一篇文献-算法】Adult neurogenesis acts as a neural regularizer

阅读时间&#xff1a;2023-12-20 1 介绍 年份&#xff1a;2022 作者&#xff1a;Lina M. Tran&#xff0c;Adam Santoro&#xff0c;谷歌DeepMind 期刊&#xff1a; Proceedings of the National Academy of Sciences 引用量&#xff1a;13 代码&#xff1a;https://github.c…