第九层(1):初识STL

简介: 第九层(1):初识STL

前情回顾


在上一层中,我见识到了C++中除了面向过程和面向对象之外的第三种编程方式——泛型编程,它可以大大提高代码复用性,主要靠模板去实现,在最后,石碑中说,学习模板不是为了写模板,而是为了更好的使用STL,STL是什么?我怀着疑问上到了第九层,抬头看到的是许久未见的天空…


🚄上章地址:第八层:模板


初识STL


在我还在看天空的时候,一道声音把我从我自己的世界中拉了出来:“别看了,这层就是C++最后一层了,你已经到达塔顶了,这层的力量很强大,同时其中需要掌握的东西很多,我看好你…""顶层了,那你人在哪?我为什么看不到你?”我带着疑问,可是那道声音的主人没有回答我,我看着前面的石碑,心里有点失落,这么长时间的学习,马上就要结束了,心里感觉空落落的…


STL的诞生


长久以来,在编程界中,一直希望建立一种可以重复利用的东西,而C++中的面向对象和泛型编程的主要目的就是提高代码的复用性,但是大多数情况下,数据结构和算法都未能有一套标志,每个人实现都有差异,但是实现内容是一样的,导致在项目中被迫从事了大量的重复工作,为了解决这种现象,就建立了数据结构和算法的一套标准,便是STL。


STL的基本概念


STL为标准的模板库,它所有的技术实现都利用到了模板技术,它从广义上讲分为了容器、算法、迭代器,其中,迭代器为连接容器和算法之间的桥梁


STL六大组件


STL分为容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器

容器:内部为各种数据结构,如vector、list、deque、set、map等,用来存放数据,所以为之容器

算法:内部为各种的常用算法,如sort、find、copy、for_each等

迭代器:扮演容器和算法之间的桥梁

仿函数:行为类似函数,可作为算法的某种策略

适配器:一种用来修饰容器或者仿函数或者迭代器接口的东西

空间配置器:负责空间的配置和管理


0a2653c851af460fa595bd959398a8f1.png


STL中的容器、算法、迭代器


STL中的容器、算法、迭代器这三个每个又能分出几个小分支


容器


容器可以分为两种:

序列式容器:强调值的排序,容器中每个元素都有固定的位置

关联式容器:二叉树结构,各元素没有严格的物理上的顺序

0eacb84100b54626af849e6b562bf92a.png


算法


算法同样分为两种:

质变算法:指运算过程中会更改区间内的元素内容,如:拷贝、替换、删除

非质变算法:运算过程中不会更改区间内元素的内容,如:查找、计数、寻找极值

2d65d23f6d4748949b924e4057485923.png


迭代器


迭代器能依序的寻找某个容器中所含的各个元素,而不会暴露改容器的内部表示方法,每个容器都有属于自己的迭代器,同时可以把迭代器理解为指针,迭代器从种类分有五种:


image.pngimage.png

image.png


容器、算法、迭代器的配合使用


上面说到迭代器是它们两个之间的桥梁,那应该怎么去搭配使用它们三个呢?在STL种最常用的容器为vector,可以理解为一个数组,那要怎么去使用这个容器放入数据呢?在使用这个容器之间,先引头文件:

#include< vector >

创建方式:

vector< 数据类型 > 变量名

迭代器:

vector< 数据类型 > :: iterator

那现在尝试写一个int类型的数组,用vector,并且设计出一种算法来打印它内部有的数据:


#include<vector>
#include<iostream>
using namespace std;
void test1()
{
  int i = 10;
  vector<int> v;
  while (i--)
  {
  v.push_back(i);//像v中上传数据
  }
  vector<int>::iterator b = v.begin();//起始迭代器,指向容器中的第一个元素位置
  vector<int>::iterator e = v.end();//结束迭代器,指向容器中最后一个元素加1的位置
  //第一种遍历方法
  while (b != e)
  {
  //解引用操作找到迭代器指向的元素
  cout << *b << " ";
  b++;
  }
  cout << endl;
}
int main()
{
  test1();
  return 0;
}


0a2653c851af460fa595bd959398a8f1.png

0a2653c851af460fa595bd959398a8f1.png

第一种可以看到代码有点长,那有没有短一点的呢?


//第二种方法
void test1()
{
  int i = 10;
  vector<int> v;
  while (i--)
  {
  v.push_back(i);//像v中上传数据
  }
  for (vector<int>::iterator b = v.begin(); b != v.end(); b++)
  {
  cout << *b << " ";
  }
  cout << endl;
}
int main()
{
  test1();
  return 0;
}

0a2653c851af460fa595bd959398a8f1.png

可以替换成for循环,其实还有第三种方法,可以利用STL中提供的算法:


for_each( v.begin , v.end , 函数)

参数中的函数是for_each()在遍历期间会调用的,for_each()遍历的多少次,这个函数就会别调用多少次,同时使用这个算法需要引头文件


#include< algorithm >

现在可以试一下第三种方法:


#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
//用于for_each中的函数
void print(int a)//因为vector为int
{
  cout << a << " ";
}
void test1()
{
  int i = 10;
  vector<int> v;
  while (i--)
  {
  v.push_back(i);//像v中上传数据
  }
  //第三种方式
  for_each(v.begin(), v.end(), print);
  cout << endl;
}
int main()
{
  test1();
  return 0;
}

0a2653c851af460fa595bd959398a8f1.png

三种方法都可以使用,凭借个人喜好来选择。

那现在存放的是编译器的内置类型,可不可以用自定义类型呢?尝试一下:


#include<vector>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
//人类
class person
{
public:
  person(string a, int b)
  {
  _name = a;
  _age = b;
  }
  string _name;
  int _age;
};
void print(person& p)
{
  cout << p._name << "的年龄为" << p._age << endl;
}
void test1()
{
  vector<person> p;
  person p1("张三", 18);
  person p2("李四", 19);
  person p3("王五", 20);
  p.push_back(p1);
  p.push_back(p2);
  p.push_back(p3);
  //第一种方法
  vector<person>::iterator b = p.begin();
  vector<person>::iterator e = p.end();
  while (b != e)
  {
  cout << b->_name << "的年龄为" << b->_age << endl;
  b++;
  }
  cout << endl;
  //第二种方法
  for (b = p.begin(); b != e; b++)
  {
  cout << b->_name << "的年龄为" << b->_age << endl;
  }
  cout << endl;
  //d第三种方法
  for_each(p.begin(), p.end(), print);
  cout << endl;
}
int main()
{
  test1();
  return 0;
}

0eacb84100b54626af849e6b562bf92a.png

可以用自定义类型,并且三种方法都可以成功,同时这里也可以看到,把迭代器当作指针使用,是没有问题的。


vector中的嵌套使用


上面说vector可以看做数组,那一个vector是个一维数组,那如果想用vector创建一个二维数组吗?如果可以怎么去创建?从二维数组去分析,二维数组的数组名代表了首元素地址,是第一个一维数组,那二维数组的本质就是一个数组里面嵌套了一堆数组,那vector是不是可以通过嵌套来实现一个二维数组?通过代码来验证一下:

现在创建一个int类型的二维数组:


#include<vector>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
void test1()
{
  vector<vector<int>> v;//创建大容器
  //创建小容器
  vector<int> v1;
  vector<int> v2;
  vector<int> v3;
  vector<int> v4;
  vector<int> v5;
  //往小容器中写入数据
  for (int i = 0; i < 6; i++)
  {
  v1.push_back(i);
  v2.push_back(i + 5);
  v3.push_back(i + 10);
  v4.push_back(i + 15);
  v5.push_back(i + 20);
  }
  //把小容器写入大容器
  v.push_back(v1);
  v.push_back(v2);
  v.push_back(v3);
  v.push_back(v4);
  v.push_back(v5);
  //通过大容器把小容器中的数都打印出来
  for (vector<vector<int>>::iterator b = v.begin(); b != v.end(); b++)//大容器的迭代器
  {
  for (vector<int>::iterator b1 = (*b).begin(); b1 != (*b).end(); b1++)//要想遍历大容器的数据,要将所有小容器遍历一遍,小容器的迭代器
  {
    cout << *b1 << " ";
  }
  cout << endl;
  }
}
int main()
{
  test1();
  return 0;
}

0a2653c851af460fa595bd959398a8f1.png

是可以这样去使用的,可以用这样的方式去创建一个二维数组。


石碑倒下…后面还有石碑?


当我掌握STL的基本使用的时候,面前的石碑倒下了,当我以为结束的时候,我看到后面还有一座石碑…


本章知识点(图片形式)


2d65d23f6d4748949b924e4057485923.png


😘预知后事如何,关注新专栏,和我一起征服C++这座巨塔

🚀专栏:C++爬塔日记

🙉都看到这里了,留下你们的👍点赞+⭐收藏+📋评论吧🙉


相关文章
|
3月前
|
NoSQL 安全 Java
2.2k star 单点登录框架揭秘!主流SSO太重?SpringBoot轻量级Smart‑SSO轻松接入·分布式·强踢人
Smart-SSO 是一个基于 SpringBoot 的轻量级单点登录框架,采用 OAuth2 授权码与 RBAC 权限设计,解决跨域认证、单点退出、令牌过期等痛点。支持自动续签、强制踢人、按钮级权限控制及分布式部署,适合中小团队快速构建高可用认证中台。项目已获 2.2k Star,代码开源,接入简单,是企业级应用的理想选择。[详情见 GitHub](https://github.com/a466350665/smart-sso)。
170 23
|
人工智能 数据可视化 定位技术
DataV AI助手小技巧-如何制作PPT数据地图
“数据地图”是PPT汇报地区业务数据的最佳形式之一;以往制作数据地图需要用户有一定的编程和数据处理基础,制作门槛较高;随着DataV整合通义千问大模型能力之后,不懂编程和设计的用户也可以借助AI助手“零代码”制作数据地图,真正实现了人人可用的地图数据可视化。 进入大模型AI时代,人人可以变成职场跨界多面手!
11796 3
DataV AI助手小技巧-如何制作PPT数据地图
|
11月前
|
存储 安全 Java
Java编程中的对象序列化与反序列化
【10月更文挑战第3天】在Java编程的世界里,对象序列化与反序列化是实现数据持久化和网络传输的关键技术。本文将深入探讨Java序列化的原理、应用场景以及如何通过代码示例实现对象的序列化与反序列化过程。从基础概念到实践操作,我们将一步步揭示这一技术的魅力所在。
|
10月前
|
Docker 容器
【赵渝强老师】Docker的Host网络模式
Docker容器在网络环境中是隔离的,可通过配置不同网络模式(如bridge、container、host和none)实现容器间或与宿主机的网络通信。其中,host模式使容器与宿主机共享同一网络命名空间,提高性能但牺牲了网络隔离性。
296 0
|
Web App开发 前端开发 Java
SpringBoot配置HTTPS及开发调试
在实际开发过程中,如果后端需要启用https访问,通常项目启动后配置nginx代理再配置https,前端调用时高版本的chrome还会因为证书未信任导致调用失败,通过摸索整理一套开发调试下的https方案,特此分享
254 0
SpringBoot配置HTTPS及开发调试
|
SQL 存储 数据库
SqlAlchemy 2.0 中文文档(一)(4)
SqlAlchemy 2.0 中文文档(一)
232 1
|
缓存 C++ Windows
Inno setup 脚本判断 Microsoft Visual C++ Redistributable 不同版本区别
Inno setup 脚本判断 Microsoft Visual C++ Redistributable 不同版本区别
|
缓存 运维 Serverless
函数计算产品使用问题之怎么优化HTTP Server的启动速度
函数计算产品作为一种事件驱动的全托管计算服务,让用户能够专注于业务逻辑的编写,而无需关心底层服务器的管理与运维。你可以有效地利用函数计算产品来支撑各类应用场景,从简单的数据处理到复杂的业务逻辑,实现快速、高效、低成本的云上部署与运维。以下是一些关于使用函数计算产品的合集和要点,帮助你更好地理解和应用这一服务。
|
数据可视化 算法
Simulink-Simscape仿真环境配置
Simulink-Simscape仿真环境配置
326 1
|
前端开发 JavaScript API
MonacoEditor 加载很慢该怎么优化?
MonacoEditor 加载很慢该怎么优化?
2501 0