当前位置: 首页 > backend >正文

C++(模板与容器)

一、模板

1.概念:

使用模板可以让程序员编写与类型无关的代码,专注于算法设计,程序运行的时候可以是任何类型,共用一套算法。

模板是泛型编程的基础,泛型编程的目的是发明一种语言机制,能够帮助实现一个通用的标准模板库STL。

2.分类:

函数模板和类模板。

2.1 函数模板

使用函数模板可以确保算法的通用性,不同类型都可以调用函数,不过算法也要确保兼容性,打印语句print传入对象肯定是不合适的,直接打印对象不合适。

#include <iostream>using namespace std;template <class T>                          //可以使用class也可以使用typename,没有本质区别
T add(T a,T b){             return a+b;
}template <typename T,typename Q>
void print(const T &a,const Q &b){          //第一次使用函数就确定传入的类型cout << a << " " << b << endl;
}int main (){cout << add(1,2) << endl;cout << add(1.2,3.3) << endl;int a = 9;string b = "adada";print(a,b);return 0;
}

 

2.2 类模板

 不确定类的成员变量以及返回值类型可以使用。

#include <iostream>using namespace std;template <class T,class Q>                   //创建两个模板
class Animal{
private:T value;Q name;
public:Animal(T value,Q name):value(value),name(name){}T get_value(){                          //定义对象的时候确定的第一种类型return value;}Q get_name(){                           //定义对象的时候确定的第二种类型return name;}
};int main (){Animal<int,string> a(4,"asdad");        //类指定变量类型,指定了类型后,这个对象的成员变量的类型就固定,别的对象创建可以单独指定类型cout << a.get_value() << " " << a.get_name() << endl;Animal<string,double> a1("zhangsan",12.5);          //a1是一个新对象,可以重新指定类型cout << a1.get_value() << " " << a1.get_name() << endl;return 0;
}

可以类内声明类外定义 

#include <iostream>using namespace std;template <class T,class Q>                   //创建两个模板
class Animal{
private:T value;Q name;
public:Animal(T value,Q name):value(value),name(name){}T get_value();                          //定义对象的时候确定的第一种类型Q get_name();                           //定义对象的时候确定的第二种类型
};template <class T,class Q>                  //类外定义,类型必须一致
T Animal<T,Q>::get_value(){                 //返回值类型和指定Animal类型保持与类的返回值和变量类型一致return value;
}template <class T,class Q>
Q Animal<T,Q>::get_name(){return name;
}int main (){Animal<int,string> a(4,"asdad");        //类指定变量类型,指定了类型后,这个对象的成员变量的类型就固定,别的对象创建可以单独指定类型cout << a.get_value() << " " << a.get_name() << endl;Animal<string,double> a1("zhangsan",12.5);          //a1是一个新对象,可以重新指定类型cout << a1.get_value() << " " << a1.get_name() << endl;return 0;
}

二、容器

1.标准模板库 STL

STL标准模板库是惠普实验室开发的一系列软件的统称。在应用于C++前已经存在很长时间。

STL 是 C++ 标准库的重要组成部分,是一套通用的、可复用的类和函数模板,用于数据结构和算法的实现。STL 让 C++ 程序员可以高效、方便地处理各种数据集合。

STL 的三大核心(广义上):容器(重要)、算法、迭代器

2.容器 container

2.1 概念:

C++ 容器(container)是 C++ 标准模板库(STL, Standard Template Library)中非常重要的组成部分。容器用于存储和管理数据集合。

容器类自动申请和释放聂村,无需new和delete操作。所有的容器类的使用都要引入对应的头文件,因为这些类型都是std名字空间下的类。

容器(Containers)有三种类型:顺序容器(重要),关联容器(重要),无序关联容器

顺序容器分为:string字符串(之前讲过),array数组,vector向量,list列表,deque队列(自行扩展练习,和别的容器类似)

 

2.2 顺序容器

是一种各元素之间有顺序关系的线性表,是一种线性结构的有序群集,按照插入顺序排序。

2.2.1 array数组

C++11引入array类型代替传统数组。相比于内置的传统数组,array更加安全和易于使用。

#include <iostream>
#include <array>using namespace std;int main (){array<int,4> arr = {1,2,3,4};           //定义int类型数组,长度为4arr[0] = 11;                            //可以使用[]取内容arr.at(1) = 22;                         //和string一样可以使用.at()取内容for(auto &i:arr){                       //循环遍历for-eachcout << i << endl;}arr.fill(-1);                           //给所有元素赋一个统一的值for(auto &i:arr){cout << i << endl;}return 0;
}

 

2.2.2 vector向量

vector相比array是长度是动态可变的,支持插入插入删除等操作,内部使用数组实现,所有元素的空间地址是连续的,所以随机存取的效率很高,插入删除的效率很低。

#include <iostream>
#include <vector>using namespace std;int main (){vector<int> vec(4);                     //初始化所有的元素都是0cout << "数组长度:" <<vec.size() << endl;             //.size函数求长度vec[0] = 11;                            //具备数组的性质,[]取元素vec.at(1) = 22;                         //也可以使用.at()函数for(auto &i:vec){                       //循环遍历cout << i << " ";}cout << endl;vec.insert(vec.begin()+2,10);           //在下标为二的位置插入一个元素,数组长度加一vec.insert(vec.begin(),100);            //在下标为零的位置插入一个元素,数组长度加一cout << "插入两个元素后数组长度:" <<vec.size() << endl;for(auto &i:vec){                       //循环遍历cout << i << " ";}cout << endl;vec.clear();                            //清空向量容器cout << "vec向量容器是否为空:" << vec.empty() << endl;            //判断当前向量容器是否为空(1是空,0是非空)for(auto &i:vec){                       //循环遍历cout << i << " ";}return 0;
}

2.2.3 list列表(重点)

list列表内部使用双向链表实现,因此list更擅长插入和删除操作,但是由于元素之间的地址不连续,随机存取的能力比较差,也不支持下标访问。(和C语言链表性质类似)

#include <iostream>
#include <list>using namespace std;int main (){list<int> lis(5);                           //创建长度为5的列表cout << "初始化链表长度为:" << lis.size() << endl;//iterator(迭代器)是一种特殊指针,高度封装list<int>::iterator iter = lis.begin();     //这里让迭代器指向列表第一个元素*iter = 11;                                 //利用iterator指针修改第一个元素数值iter ++;                                    //指针后移指向下一个list元素*iter = 22;                                 //修改列表第二个数值for(auto i:lis){                            //循环遍历列表cout << i << " ";}cout << endl;lis.push_front(101);                        //在列表第一个位置添加一个元素lis.push_back(44);                          //在列表最后一个为位置添加一个元素for(auto i:lis){                            //循环遍历cout << i << " ";}cout << endl;cout << *iter << endl;                      //指针依旧指向数值为22的元素advance(iter,2);                            //后移两个位置(可以跳过头结点)advance(iter,-3);                           //后移三个位置cout << *iter << endl;//.begain()返回的指针指向第一个元素,.end()返回的是最后一个元素后一个元素,可以这么理解,尾节点后面还有一个节点元素和头结点元素值一样,所以.begin()返回的地址第一次--的值还是第一个元素的值,.end()一样。iter = lis.begin();                         //复位,让iter指针指向第一个位置元素iter --;cout << *iter << endl;iter = lis.end();                           //让iter指针指向第一个位置后面的元素iter ++;cout << *iter << endl;lis.sort();                                 //从小到大排序for(auto i:lis){                            //循环遍历cout << i << " ";}cout << endl;iter = lis.end();                           //前面排序后,iter指针指向的链表不存在,要重新复位advance(iter,-4);                           //移到倒数第四个元素lis.erase(iter);for(auto i:lis){                            //循环遍历cout << i << " ";}cout << endl;lis.clear();                                //清空列表cout << "列表是否为空:" << lis.empty()<<endl;for(auto i:lis){                            //循环遍历cout << i << " ";}return 0;
}

2.2.4 deque队列

deque是一种均衡的容器才,从接口上几乎兼容vector和list的功能,新能介于二者之间。

2.3 关联容器

主要讲解map:键值对映射

关联的元素没有严格的顺序关系,但是内部有排序,因此才可以被迭代器遍历

元素的数据被称为值(value),每个元素拥有一个第一无二的名称:键(key),所以一个完整的元素被称为键值对。

#include <iostream>
#include <map>using namespace std;int main (){map<string,int> map1;               //创建一个关联容器//增加元素map1["身高"] = {178};map1.insert(pair<string,int>("月薪",20000));map1.insert(pair<string,int>("身高",188));  //第一个键是唯一的,第二次插入一样的键不会修改值//两种方式取出数据cout << map1["月薪"] << endl;cout << map1.at("身高") << endl;//没有该键的时候会创建一个值为零点键cout << map1["年龄"] << endl;cout << "关联容器map1长度:" << map1.size() << endl;//判断键值对是否存在map<string,int>::iterator iter = map1.find("年龄");//删除键值对if(iter == map1.end())      //如果find没找到键返回的是尾节点地址cout << "无法删除,查无此键!" << endl;elsemap1.erase("年龄");map1.clear();                               //清空关联容器cout << "关联容器map1长度:" << map1.size() << endl;cout << "关联容器map1是否为空:" << map1.empty() << endl;return 0;
}

2.4 迭代器 iterator

容器的遍历通常都是使用迭代器进行的,C++标准库为每一种容器都提供了对应的迭代器类型。

迭代器如同一个指针,但是迭代器又不仅仅是指针。

每种容器都定义了特殊的函数,用于返回所需类型的迭代器,通常情况下使用begin函数获得顺序迭代器类型,表示只读。

还有const_interator类型,表示只读。

#include <iostream>
#include <string>
#include <array>
#include <vector>
#include <list>
#include <deque>
#include <map>using namespace std;int main (){//string容器cout << "string容器:";string str = "ABCDEFG";for(string::const_iterator iter = str.begin();iter != str.end();iter ++){cout << *iter << " ";}cout << endl;//array容器cout << "array容器:";array<string,7> arr = {"Any","Boy","Cat","Dog","Each","Far","God"};for(array<string,7>::const_iterator iter = arr.begin();iter != arr.end();iter ++){cout << *iter << " ";}cout << endl;//vector容器cout << "vector容器:";vector<string> vec = {"Any","Boy","Cat","Dog","Each","Far","God"};      //使用初始化列表for(vector<string>::const_iterator iter = vec.begin();iter != vec.end();iter ++){cout << *iter << " ";}cout << endl;//deque容器cout << "deque容器:";deque<string> deq = {"Any","Boy","Cat","Dog","Each","Far","God"};{deque<string>::const_iterator iter = deq.begin();while(iter != deq.end()){cout << *iter << " ";iter ++;}cout << endl;}//list容器cout << "list容器:";list<string> lis = {"Any","Boy","Cat","Dog","Each","Far","God"};{list<string>::const_iterator iter = lis.begin();while(iter != lis.end()){cout << *iter << " ";iter ++;}cout << endl;}//关联容器cout << "关联容器:" << endl;map<string,int> map1 = {{"身高",178},{"体重",121},{"年龄",22},{"薪资",18000}};for(map<string,int>::const_iterator iter = map1.begin();iter != map1.end();iter ++){cout << iter->first << ":" << iter->second << endl;}return 0;
}

http://www.xdnf.cn/news/14720.html

相关文章:

  • python中学物理实验模拟:斜面受力分析
  • 苍穹外卖day3--公共字段填充+新增菜品
  • python基于协同过滤的动漫推荐系统
  • 【51单片机5毫秒定时器】2022-6-1
  • Linux 内核 TCP 的核心引擎:tcp_input.c 与 tcp_output.c 的协同之道
  • Miniconda+Jupyter+PyCharm初始环境配置
  • 物联网与低代码:Node-RED如何赋能工业智能化与纵横智控的创新实践
  • 【已解决】Android Studio gradle遇到unresolved reference错误
  • 【机器学习深度学习】线性回归
  • 【thinkphp5】Session和Cache记录微信accesstoken
  • 【原创】【4】【辅助工具】基于视觉模型+FFmpeg+MoviePy实现短视频自动化二次编辑+多赛道
  • Gartner《敏捷化组织团队拓扑方法论》学习心得
  • [特殊字符]推客带货小程序解决方案——0门槛裂变营销,佣金赚不停!
  • 华为交换机 USG6311E 新建 vlan
  • 海澜之家旗下斯搏兹选择百胜软件,E3+企业中台持续为运动品牌业务发展赋能
  • Node.js特训专栏-实战进阶:9.MySQL连接池配置与优化
  • Java全栈面试实录:从电商平台到AIGC,技术栈深度解析
  • 领域驱动设计(DDD)【13】之重构中的坏味道:深入理解依恋特性(Feature Envy)与表意接口模式
  • 八股文——JAVA基础:基本数据类型与包装类的区别
  • 基于 Python 的批量文件重命名软件设计与实现
  • FPGA基础 -- Verilog 建模示例之通用移位寄存器
  • Linux远程机器无法连接-------解决方案
  • Python 数据分析与可视化 Day 7 - 可视化整合报告实战
  • 基于 opencv+yolov8+easyocr的车牌追踪识别
  • UniApp 开发第一个项目
  • 专题:2025医疗AI应用研究报告|附200+份报告PDF汇总下载
  • 【网络实验】-配置用户登录
  • WeakAuras Lua Script [ICC BOSS 12 - The Lich King]
  • 在ASP.NET Core WebApi中使用标识框架(Identity)
  • error: GH013: Repository rule violations found for refs/heads/main.