模板、STL标准模板库

模板

通常 对 具有相同要求的结果或者类 提供一个模板,根据实际使用时传过来的数据类型,决定函数和类的具体实现。
模板可以让类或者函数支持一种类型,这种通用类型在实际运行的过程中可以使用任何数据类型。
这种编程方式也成为"泛型编程"。

模板函数

如果函数除了参数类型和返回值类型以外,其他部分全部相同,就可以使用模板来定义函数。

template <typename T> // T:数据类型
template <typename T1, typename T2, …>

#include <iostream>
using namespace std;template <typename T>		// 模板只对下面的第一个函数有效
T func()					// 参数没有使用模板中的类型,或者无参,不能通过函数调用直接推导出 T 的类型
{							// 需要显性调用模板return 38;
}template <typename T>		// 模板只对下面的第一个函数有效
T func(T a, T b)			// 两个参数都是模板的数据类型,可以通过函数调用推导出模板类型
{							// 隐性调用模板return a > b ? a : b;
}template <typename T1, typename T2>			// 模板只对下面的第一个函数有效
T2 add(T1 a, T1 b)
{	T2 num;					// 模板提供的数据类型也可以在函数里面定义变量使用return a + b;
}int main()
{int num1 = 9;int num2 = 6;cout << func<char>() << endl;cout << func(num1, num2) << endl;cout << func(6, 9) << endl;			// 若用小数,必须每个值都用小数,∵T func(T a, T b)cout << add<int, int>(num1, num2) << endl;cout << add<float, float>(6, 9) << endl;return 0;
}

在这里插入图片描述

模板类

如果要 给模板类的成员函数 实现 类内声明类外定义,需要在类外定义的位置再重写一次模板,并且,类要使用显性调用模板来实现。

#include <iostream>
using namespace std;// 实现模板类
template <typename T>			// 可以使用 class,也可以使用 typename
class Complex
{T real;T vir;
public:Complex() { }Complex(T real, T vir):real(real), vir(vir) { }void set_(T real, T vir);  // 模板类中的成员函数,可以实现类内声明,类外定义,需要重写模板void show();			   // 模板类中的成员函数也可以在类内定义
};template <typename T>  		// 只对下面一个模板函数有效
void Complex<T>::set_(T real, T vir)
{this->real = real;this->vir = vir;
}template <typename T>		// 只对下面一个模板函数有效
void Complex<T>::show()
{cout << real << "+" << vir << "i" << endl;
}int main()
{Complex<int> com(3, 4);com.show();com.set_(5, 12);com.show();return 0;
}

在这里插入图片描述

STL 标准模板库(Standard Template Library)

https://en.cppreference.com/w/(👈,放心跳转)
在这里插入图片描述

标准模板库(Standard Template Library,STL)是惠普实验室开发的一系列软件的统称。虽说它主要出现到了 C++ 中,但是在被引入 C++ 之前该技术就已经存在了很长时间。
STL 的代码从广义上讲分为三类:algorithm(算法)、container(容器)和 iterator(迭代器),几乎所有的代码都采用了模板类和模板函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。

C++ Iterators(迭代器)

迭代器是一个特殊的指针,主要用于元素的读写以及遍历。
在这里插入图片描述

找指定位置的迭代器

由于容器类只能找起始位置和结束位置的迭代器,所以只能在已有迭代器的位置上自增,和指针类似。访问元素需要解引用,但是不能像指针类型一样强转。

容器名<数据类型> ::iterator 迭代器名;

迭代器遍历

如果 迭代器不进行修改操作,建议使用只读迭代器 const_iterator,反之使用 iterator。
#include <iostream>
#include <array>
#include <vector>
#include <list>
#include <deque>
#include <map>using namespace std;int main()
{// stringstring s = "abcdefg";for(string::const_iterator iter = s.begin();iter != s.end(); iter++){cout << *iter;}cout << endl;cout << "-----------" << endl;// arrayarray<int, 5> arr = {21, 2, 4, 67, 3};for(array<int, 5>::const_iterator iter = arr.begin();iter != arr.end(); iter++){cout << *iter << " ";}cout << endl;cout << "-----------" << endl;// vectorvector<string> vec(6, "world");for(vector<string>::const_iterator iter = vec.begin();iter != vec.end(); iter++){cout << *iter << " ";}cout << endl;cout << "-----------" << endl;// listlist<string> lis(5, "hello");for(list<string>::const_iterator iter = lis.begin();iter != lis.end(); ++iter) 		// 等同于 iter++{cout << *iter << " ";}cout << endl;cout << "-----------" << endl;// dequedeque<string> de(6, "Hola~");for(deque<string>::const_iterator it = de.begin();it != de.end(); it++){cout << *it << " ";}cout << endl;cout << "-----------" << endl;// mapmap<string, int> ma;ma["waistline"] = 66;ma["type"] = 1;ma["height"] = 188;ma["asset"] = 202300;for(map<string, int>::const_iterator i = ma.begin();i != ma.end(); i++){// first 是键(key),second 值(val)cout <<  i->first << " " << i->second << endl;}return 0;
}

在这里插入图片描述

容器(= 顺序容器 + 关联容器)

用来存储数据的集合,数据元素可以是任何类型(因为是使用模板进行实现的)。
容器类的使用,需要引入对应的头文件。
在这里插入图片描述

顺序容器

顺序容器中每个元素均有固定的位置并呈现线性排布,
除非使用删除或者插入的操作改变原来元素的位置。

Array 数组

array 数组是 C++11 新增的容器类型,与传统数组相比更加安全,易于使用。array 数组是定长的。

EXAMPLE
#include <iostream>
#include <string.h>
#include <array>  						// 头文件using namespace std;int main()
{// 创建一个长度为 5 的 int 数组array<int, 5> arr = {1, 2, 3}; 		// 后面两位补零cout << arr[0] << endl; 			// 1cout << arr[4] << endl; 			// 0cout << arr.at(2) << endl; 			// 3,推荐使用 at函数(安全)arr[3] = 200;cout << "------------" << endl;// for 循环遍历for(int i = 0; i < arr.size(); i++){cout << arr.at(i) << endl;}cout << "------------" << endl;// for each 遍历for(int i : arr){cout << i << endl;}return 0;
}

在这里插入图片描述

Vector 向量

vector 的行为和数组类似,可以理解为顺序表。
vector 内部是由数组实现的,比较适合进行随机的存取操作,不擅长插入和删除操作
vector 不需要判满,动态分配内存:如果存入新的数据,会再开辟一片更大的空间,把原来的内容拷贝过去。
在这里插入图片描述

构造函数

在这里插入图片描述

Functions
bool empty();

在这里插入图片描述

size_type size();

在这里插入图片描述

TYPE at (size_type loc);

在这里插入图片描述

iterator begin();

在这里插入图片描述

iterator end();

在这里插入图片描述

void push_back (const TYPE &val);

在这里插入图片描述

size_type capacity();

在这里插入图片描述

void pop_back();

在这里插入图片描述

TYPE front();

在这里插入图片描述

TYPE back();

在这里插入图片描述

insert 函数

iterator insert (iterator loc, const TYPE &val);
void insert (iterator loc, size_type num, const TYPE &val);
void insert (iterator loc, input_iterator start, input_iterator end);

在这里插入图片描述

assign 函数

void assign (input_iterator start, input_iterator end);
void assign (size_type num, const TYPE &val);
在这里插入图片描述

EXAMPLE
#include <iostream>
#include <vector>
using namespace std;int main()
{vector<int> v1;   		// 调用 vector 的无参构造vector<int> v2(5, 3);vector<int> v3(v2);   	// 调用拷贝构造cout << v1.empty() << endl;		// 判断 v1 是否为空cout << "元素个数:" << v2.size() << endl;   	// 输出 v2 容器中元素的个数cout << "v2的大小:" << v2.capacity() << endl;  	// 5v2.push_back(89);				// 尾插cout << "元素个数:" << v2.size() << endl;cout << "v2的大小:" << v2.capacity() << endl;  // 插入一个元素后,是 10,二倍扩容cout << "V2中的元素:" << endl;v2.push_back(89);cout << "\t push 后元素个数:" << v2.size() << endl;v2.pop_back();cout << "\t pop 后元素个数:" << v2.size() << endl;cout << "v2的大小:" << v2.capacity() << endl;v2.front() = 45;v2.back() = 78;// 在第三个位置前插入元素,需要用到 insert 函数vector<int>::iterator pos = v2.begin()+2;v2.insert(pos, 29);vector<int>::iterator temp;   // 定义一个可以遍历 <int> 模板的 vector 容器的迭代器for (temp = v2.begin(); temp != v2.end(); temp++)cout << *temp << "\t";  //对迭代器解引用操作,访问到具体的元素cout << endl;cout << *(v2.end()-1) << endl;/*cout << v2.front() << endl;  		// 返回对象的引用cout << v2.back() << endl;*/cout << v2.size() << endl;pos = v2.begin()+4;  		// 和指针的操作相同,从第一个迭代器找下一个迭代器直接 +1temp = v2.end();v2.assign(pos, temp);for (temp = v2.begin(); temp != v2.end(); temp++){cout << *temp << "\t";  //对迭代器解引用操作,访问到具体的元素}cout << endl;return 0;
}

在这里插入图片描述

( begin / end ) v.s. ( front / back )

begin 和 end 成员函数,返回起始位置和结尾位置的迭代器;
front 和 back 成员函数,返回起始位置和结尾位置的引用。

vector 的二倍扩容

vector<int> v2(5, 3); // 第一次开辟 5 个 int 型 大小(5个3)
v2.push_back(89); // v2 容器中元素满,再插入 89,则再开辟 5 个 int 型 大小
// 若再满,再插入,则再开辟 10 个 int 型 大小。然后是 20,40…以此类推。

List 双向链表

list 内部有双向循环链表的实现,内存空间不连续,不支持下标。
可以进行高效的删除和添加操作,但是不适合随机存取。

#include <iostream>
#include <list> 				// 头文件
using namespace std;int main()
{// 创建一个默认无数值的 list// list<string> lis1;// 创建一个长度为 2 的列表,第一个元素 "hello",第二个元素 "world"
//    list<string> lis2{"hello", "world"};
//    for(string s : lis2)
//    {
//        cout << s << endl;
//    }// 创建一个长度为 5 的列表,每个元素都是 "hello"list<string> lis(5, "hello");// 增lis.push_back("world"); 			// 向后追加单元素lis.push_front("hahaha"); 			// 向前追加单元素lis.insert(++lis.begin(), "222"); 	// 在第二个位置上插入"222"for (list<string>::iterator iter = lis.begin(); iter != lis.end(); iter++)cout << *iter << ", ";cout << endl << "----------------" << endl;// 删lis.pop_back(); 			// 删除最后一个元素lis.pop_front(); 			// 删除第一个元素// 迭代器list<string>::iterator iter = lis.begin();advance(iter, 1); 			// 移动迭代器指针到固定位置lis.insert(iter, "333");lis.push_back("world"); // 向后追加单元素// 删除最后一个元素iter = lis.end();iter--;lis.erase(iter);// 删除iter = lis.begin();advance(iter, 1);lis.erase(iter);// 返回最后一个元素cout << "The last: " << lis.back() << endl;// 返回第一个元素cout << "The first: " << lis.front() << endl;cout << "----------------" << endl;// 不能用普通循环遍历,因为不支持下标for(string s : lis){cout << s << endl;}cout << "Size = " <<lis.size() << endl;lis.clear();cout << "Size = " << lis.size() << endl;return 0;
}

在这里插入图片描述

Deque 双端队列

队列几乎支持所有 vector 的API,性能位于 vector 与 list 二者之间,是擅长两端存取的顺序容器。

#include <iostream>
#include <deque>			// 头文件
using namespace std;int main()
{//    deque<int> v(5);
//    for(int i : v)
//    {
//        cout << i << endl;
//    }// 创建一个长度为 5 的 int 向量deque<int> vec = {1, 2, 3, 4, 5};// 增// 向后追加一个元素vec.push_back(222);// cout << vec.size() << endl;// begin()可以返回指向第一个元素的迭代器指针,+2是在第三个位置上插入333vec.insert(vec.begin()+2, 333); // 1 2 333 3 4 5 222// 删// 删除最后一个元素vec.pop_back(); 				// 1 2 333 3 4 5// 删除第二个元素vec.erase(vec.begin() + 1);		// 1 333 3 4 5// 删除倒数第二个元素vec.erase(vec.end() - 2); 		// 1 333 3 5// 改vec.at(2) = 666; 				// 1 333 666 5vec[1] = 222;   				// 1 222 666 5// 查cout << vec.at(1) << endl;cout << vec[0] << endl;// 遍历for(int i :vec){cout << i << " ";}cout << endl;cout << "-----------" << endl;for(int i = 0; i < vec.size(); i++){cout << vec[i] << " " ;}cout << endl;cout << "-----------" << endl;// 判断是否为空,0:非空 1:空cout << vec.empty() << endl;// 清空vec.clear();cout << vec.empty() << endl;return 0;
}

在这里插入图片描述

关联容器

关联容器的各元素之间没有严格的顺序,虽然内部具有排序特点,但在使用时没有任何顺序相关接口。
最常见的关联容器就是 map —— 键值对映射。

Map

对于 map 而言,键具有唯一性,键通常使用字符串类型,
值可以是任何类型,通过键可以找到对应的值。
在这里插入图片描述

#include <iostream>
#include <map> 					// 头文件
using namespace std;int main()
{// 列表初始化创建 c++11 支持
//    map<string, int> ma1 = {{"年龄", 5}, {"身高", 200}};
//    cout << ma1.size() << endl; 					// 2// 创建一个元素为 0 的键值对对象map<string, int> ma;cout << ma.size() << endl;ma["height"] = 185; 							// 插入元素ma.insert(pair<string, int>("weight", 140)); 		// 插入元素// 查cout << "Height: " << ma["height"] << endl;cout << "Weight: " << ma["weight"] << endl;// 改ma["height"] = 188;cout << "Height: " << ma["height"] << endl;// 删if(ma.find("weight") == ma.end()){cout << "Cannot find the key named \"weight\"! "<< endl;}else{int re = ma.erase("weight");cout << "Succeeded or not: " << re << endl;}cout << ma.size() << endl;ma.clear();cout << ma.size() << endl;return 0;
}

在这里插入图片描述

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

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

相关文章

画图带你理清TCP协议三次握手和四次挥手

TCP 特性 1.确认应答机制 (ACK) 2.超时重传 3.建立连接 - 三次握手 4.断开连接 - 四次挥手 1.确认应答机制 (ACK) 确认应答是可靠传输的最核心机制&#xff0c;接收方反馈一个应答报文(ACK)&#xff0c;表示已收到 假设现在 A 想去 B 家里玩游戏&#xff0c;于是 A 给…

SEO外链工具,免费SEO引蜘蛛工具

随着互联网的迅猛发展&#xff0c;网站的排名成为各类企业的突破口。SEO&#xff08;Search Engine Optimization&#xff09;作为提高网站在搜索引擎中排名的重要手段&#xff0c;其成功与否直接关系到网站能否获得更多的曝光和流量。在SEO的世界中&#xff0c;引蜘蛛与外链的…

6-3 求3*3整数矩阵对角线元素之和

#include<stdio.h>int main(){int a[3][3],sum0;int i ,j;printf("输入元素&#xff1a;\n");for(i0;i<3;i)for(j0;j<3;j)scanf("%d",&a[i][j]);for(i0;i<3;i)sumsuma[i][i];printf("总和为&#xff1a;%d",sum);return 0;}

如何购买阿里云服务器

作为一家全球领先的云计算服务提供商&#xff0c;阿里云提供了多种云产品和解决方案&#xff0c;包括云服务器、对象服务OSS、数据库、存储、SSL、域名和CDN等。阿里云服务器是一种灵活可扩展的云计算服务&#xff0c;适用于各种规模和类型的企业和个人用户。阿里云以其出色的性…

邮件迁移-邮件同步-批量完成邮件迁移解决方案-imapsync

背景&#xff1a; 公司原来使用的邮箱服务器实现方式是james的cassandra-app&#xff0c;如今要启用新的邮件服务器&#xff0c;架构用的是james的distributed-app,升级后&#xff0c;要求邮件数据不丢失&#xff0c;因此要平滑完成邮件的迁移工作&#xff0c;保障升级后邮件不…

文章解读与仿真程序复现思路——中国电机工程学报EI\CSCD\北大核心《考虑量化储热的多区域电–热综合能源系统优化调度》

标题 "考虑量化储热的多区域电–热综合能源系统优化调度" 可以分解为几个关键词和短语&#xff0c;我们逐步解读&#xff1a; 考虑量化储热&#xff1a; 考虑&#xff1a; 意味着在解决问题或进行研究时&#xff0c;会综合或纳入特定因素。量化&#xff1a; 将抽象的…

旺店通·企业奇门对接打通金蝶云星空查询店铺接口与客户新增接口

旺店通企业奇门对接打通金蝶云星空查询店铺接口与客户新增接口 数据源系统:旺店通企业奇门 旺店通是北京掌上先机网络科技有限公司旗下品牌&#xff0c;国内的零售云服务提供商&#xff0c;基于云计算SaaS服务模式&#xff0c;以体系化解决方案&#xff0c;助力零售企业数字化智…

android.view.WindowLeaked解决方法

问题 我在使用WindowManager添加一个button&#xff0c; windowManager.addView(button,layoutParams);然后关闭当前的这个Activity的时候遇到了WindowLeak这个问题&#xff0c;也就是所谓的窗体泄露。 原因 主要原因是因为android只允许在UI主线程操作&#xff0c;我在使用W…

编译原理实验词法分析

编译原理实验中的词法分析是编译过程的一个重要环节。它的任务是从左到右读入源程序的字符流&#xff0c;识别出一个个的单词&#xff0c;即基本保留字、标识符、常数、运算符、分隔符五大类。 在识别出下一个单词后&#xff0c;词法分析程序会验证其词法正确性&#xff0c;然…

卖家低价侵权了怎么处理

店铺如果未经品牌允许&#xff0c;做了产品销售&#xff0c;其实从知识产权的角度出发&#xff0c;对于品牌来说&#xff0c;店铺这种行为属于侵权&#xff0c;侵犯了品牌的商标权、著作权、专利权等&#xff0c;所以品牌可以对店铺进行知识产权维权&#xff0c;店铺如果未授权…

崩坏:星穹铁道《渔工案周年特别篇》读后感,有多少恶搞柯南的地方

在星穹铁道1.5版本中&#xff0c;智库新上线一本读物&#xff0c;名为《渔工案周年特别篇》读后感。 《渔工案周年特别篇》读后感可以说是恶搞了大量柯南的梗和目前柯南的槽点了&#xff0c;看的有些搞笑。 《渔工案》在此前1.3版本里面&#xff0c;三月七的说出渔工案内容&…

GPT4-Turbo技术原理研发现状及未来应用潜力分析报告

今天分享的是GPT4-Turb系列深度研究报告&#xff1a;《GPT4-Turbo技术原理研发现状及未来应用潜力分析报告》。 &#xff08;报告出品方&#xff1a;深度行业分析研究&#xff09; 报告共计&#xff1a;46页 图像理解能力提升&#xff1a;三大视觉学习方法  为打造视觉大模…

成品短视频app源码开发,你需要知道的最新动向

随着移动互联网的快速发展&#xff0c;短视频行业正迅速崛起。越来越多的创业者和开发者将目光投向了成品短视频app源码开发领域。下面我们将深入探讨这一领域的最新动向&#xff0c;带您了解成品短视频app源码开发的趋势与前景 成品短视频app源码开发的前景和机遇 短视频内容…

深圳招聘一般在哪个网站

深圳吉鹿力招聘网是一个专注于深圳招聘的平台&#xff0c;主要提供人才招聘服务。在深圳吉鹿力招聘网上&#xff0c;你可以找到各种深圳招聘信息&#xff0c;包括企业招聘、职位发布、简历投递等。深圳吉鹿力招聘网的出现&#xff0c;方便了求职者的投递和查询工作机会&#xf…

36、红外遥控(外部中断)

红外遥控简介 红外遥控是利用红外光进行通信的设备&#xff0c;由红外LED将调制后的信号发出&#xff0c;由专用的红外接收头进行解调输出 通信方式&#xff1a;单工&#xff0c;异步 红外LED波长&#xff1a;940nm 通信协议标准&#xff1a;NEC标准 硬件电路 基本发送与接收…

基于Spring Cloud智慧工地可视化管理平台源码

智慧工地是聚焦工程施工现场&#xff0c;紧紧围绕人、机、料、法、环等关键要素&#xff0c;综合运用物联网、云计算、大数据、移动计算和智能设备等软硬件信息技术&#xff0c;与施工生产过程相融合。 一、什么是智慧工地 智慧工地是指利用移动互联、物联网、智能算法、地理…

OpenAI发生的大事件总结!

在 11 月的最后一天&#xff0c;OpenAI 官网发布了一则公告&#xff0c;宣布 Sam Altman 再次担任首席执行官&#xff0c;并成立了新的初始董事会。这项持续了 12 天的事件终于得到了解决&#xff0c;OpenAI 回到了正常运营轨道上。 一切仍然保持不变&#xff1a; Sam Altman仍…

基于PHP的在线日语学习平台

有需要请加文章底部Q哦 可远程调试 PHP在线日语学习平台 一 介绍 此日语学习平台基于原生PHP开发&#xff0c;数据库mysql。系统角色分为用户和管理员。(附带参考设计文档) 技术栈&#xff1a;phpmysqlphpstudyvscode 二 功能 学生 1 注册/登录/注销 2 个人中心 3 查看课程…

智能优化算法应用:基于热交换算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于热交换算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于热交换算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.热交换算法4.实验参数设定5.算法结果6.参考文献7.…

Bishop新著 - 深度学习:基础与概念 - 前言

译者的话 十几年前&#xff0c;笔者在MSRA实习的时候&#xff0c;就接触到了Christopher M, Bishop的经典巨著《Pattern Recogition and Machine Learning》(一般大家简称为PRML)。Bishop大神是微软剑桥研究院实验室主任&#xff0c;物理出身&#xff0c;对机器学习的基本概念…