STL介绍
1.STL(Standard TemplateLibrary,标准模板库)
2.STL提供了六大组件:容器,算法,迭代器,仿函数,适配器,空间配置器
容器:各种数据结构
算法:各种常用的算法(冒泡,排序)
迭代器:扮演了容器与算法之间的胶合剂(类似于指针等)
仿函数:行为类似函数,可作为算法的某种策略
适配器:一种用来修饰容器或者仿函数或迭代器接口的东西
空间配置器:负责空间的配置与管理
STL六大组件的交互关系,容器通过空间配置器取得数据存储空间,算法通过迭代器存储容器中的内容,仿函数可以协助算法完成不同的策略的变化,适配器可以修饰仿函数。
三大组件(重点)
容器:序列式容器和关联式容器
序列式容器:序列式容器就是容器元素在容器中的位置是由元素进入容器的时间和地点来决定
关联式容器:关联式容器是指容器已经有了一定的规则,容器元素在容器中的位置由容器的规则来决定
算法分为:质变算法和非质变算法
质变算法::是指运算过程中会更改区间内的元素的内容
非质变算法:是指运算过程中不会更改区间内的元素内容
迭代器:重点学习双向迭代器和随机访问迭代器
双向迭代器:++,--可以访问下一个元素和上一个元素
随机访问迭代器:+2,可以跳2个元素访问元素
三大组件的关系:容器存储数据,并且提供迭代器,算法使用迭代器来操作容器中的元素
STL的工作机制(重点)
//模版 template <class T> class MyAarray { public: //给T* 取别名 iterator = T* typedef T* iterator; //保护原生指针,给原生指针取别名 //默认构造 //容量=10 大小等于10 MyAarray() { mCapacity = 10; mSize = 10; p = new T[mCapacity]; //堆区开辟数组 for (int i = 0; i < mCapacity; i++) { p[i] = i + 1; //赋值1 --10 } } ~MyAarray() { if (p != nullptr) { delete[]p; p = nullptr; } } //迭代器开始:返回数组首地址 T* begin() { return p; } //迭代器结束:返回 首地址加大小(最后一个元素的下一个位置) T* end() { return p + mSize; } private: T* p; //指向数组的指针 int mCapacity; //总容量 int mSize; //当前元素个数 }; template <class T> void printArray(T begin, T end) { for (; begin != end; begin++) { cout << *begin << " "; } cout << endl; } void test1() { MyAarray<int>arr; MyAarray<int>::iterator begin = arr.begin(); MyAarray<int>::iterator end = arr.end(); printArray(begin, end); } int main() { test1(); return 0; }随机访问迭代器
iterator=T*begin()返回数组第一个元素地址end()返回最后一个元素的下一个地址(STL 标准规范)总结
STL 三大组件:
- 容器:
MyArray存储数据- 迭代器:
iterator遍历容器,给算法提供接口- 算法:
printArray通用处理数据容器和算法通过迭代器进行解耦,算法不依赖容器,这就是 STL 的设计思想!
容器存储的三种类型
基础数据类型
vector容器
- 是 STL 中最常用的序列式容器,相当于动态数组。
- 常用方法:
push_back()尾部插入、begin()/end()获取迭代器void test1() { vector<int>v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(3); v.push_back(3); v.push_back(4); v.push_back(5); vector<int>::iterator pStard = v.begin(); vector<int>::iterator pEnd = v.end(); while (pStard != pEnd) { cout << *pStard << " "; pStard++; } cout << endl; //此时迭代器已经在末尾了,需要重新获取 pStard = v.begin(); //算法cout 是用来统计x元素d个数 int n = count(pStard, pEnd, 3); cout << "n: " << n << endl; }int n = count(pStart, pEnd, 3);
功能:统计区间 [pStart, pEnd)中,值等于 3的元素总个数,并把结果存到变量
n里。
类对象
STL 容器不单单可以存储基础数据类型,也可以存储类对象
//STL 容器不仅可存数据类型,还可以存类对象 class Student { public: Student(int age) :_age(age) {} ~Student() {} int getAge() { return _age; } private: int _age; }; void test2() { Student s1(10), s2(20), s3(30), s4(40); vector<Student> v; v.push_back(s1); v.push_back(s2); v.push_back(s3); v.push_back(s4); vector<Student>::iterator pStard = v.begin(); vector<Student>::iterator pEnd = v.end(); while (pStard != pEnd) { cout << pStard->getAge() << " "; pStard++; } cout << endl; }
类指针
class Student { public: Student(int age) :_age(age) {} ~Student() {} int getAge() { return _age; } private: int _age; }; void test3() { //new delete Student* s1 = new Student(10); Student* s2 = new Student(20); Student* s3 = new Student(30); Student* s4 = new Student(40); Student* s5 = new Student(50); vector<Student*>v; v.push_back(s1); v.push_back(s2); v.push_back(s3); v.push_back(s4); v.push_back(s5); vector<Student*>::iterator pStart = v.begin(); vector<Student*>::iterator pEnd= v.end(); while (pStart != pEnd) { //存储器存指针必须先解引用 cout << (*pStart)->getAge ()<< " "; pStart++; } cout << endl; //此时迭代器已经在末尾,需要重新获取 //释放 pStart = v.begin(); while (pStart != pEnd) { delete* pStart; pStart++; } }
嵌套容器
- 容器嵌套容器 = 二维结构,必须两层遍历
- 小容器一定要
push_back进大容器,否则是空的- 外层迭代器 → 拿到小容器;内层迭代器 → 拿到真实数据
//嵌套容器 void test4() { vector<vector<int>>v; vector<int>v1, v2, v3; v1.push_back(1); v1.push_back(2); v1.push_back(3); v2.push_back(10); v2.push_back(20); v2.push_back(30); v3.push_back(100); v3.push_back(200); v3.push_back(300); v.push_back(v1); v.push_back(v2); v.push_back(v3); //拿到容器迭代器 vector<vector<int>>::iterator pStart = v.begin(); vector<vector<int>>::iterator pEnd = v.end(); //迭代器遍历 while (pStart != pEnd) { //获得当前容器迭代器 vector<int>vTmp = *pStart; vector<int>::iterator tmpStart = vTmp.begin(); vector<int>::iterator tmpEend = vTmp.end(); for (; tmpStart != tmpEend; tmpStart++) { cout << *tmpStart << " "; } cout << endl; pStart++; } cout << endl; }
总结
1. 存储基础类型
vector<int>cout << *it;2. 存储类对象
vector<Student>cout << it->getAge();3. 存储类指针
vector<Student*>(最容易错)cout << (*it)->getAge();口诀:存指针 → 先 * 解引用迭代器,再 -> 访问成员
4. 容器嵌套容器
vector<vector<int>>
相当于二维数组
必须两层遍历:外层拿小容器,内层拿数据
二、迭代器通用规则
begin()指向第一个元素
end()指向最后一个元素的下一个位置遍历完后,迭代器会跑到末尾,再次使用必须重置:
it = v.begin();三、count 算法
int n = count(开始迭代器, 结束迭代器, 目标值);作用:统计某个值出现的次数
四、类的访问规则(封装)
public:类内外都能访问
private:类外不能直接访问,必须用get/set函数五、new /delete 必须配对
vector<Student*>用new创建对象最后必须遍历释放,防止内存泄漏
delete *it;六、3 句万能口诀
存对象用
->,存指针用(*it)->迭代器用完要归位,不然统计全是 0
new 完必须 delete,private 不能直接访问