C++ STL标准模板库简介
文章目录
- 1. 什么是STL?
- 2. STL的优势
- 3. STL版本?
- 4. STL的六大组件
- 5. 学习建议
- 6. 为什么需要迭代器?
- 7. 自己实现迭代器iterator
- 8. STL中的5种迭代器
- 9. STL中的iterator类
- 10. 序列容器对比
- 11. 容器适配器对比
- 12. 关联容器对比
C++ STL标准库系列文章:
[STL] 1.简介
[STL] 2.序列容器 固定数组array(C++ 11)
[STL] 3.序列容器 动态数组vector
[STL] 4.序列容器 双端队列deque
[STL] 5.序列容器 双向链表list
[STL] 6.序列容器 单向链表forward_list(C++ 11)
[STL] 7.适配器简介
[STL] 8.容器适配器 栈stack
[STL] 9.容器适配器 队列queue
[STL] 10.容器适配器 优先队列priority_queue
[STL] 11.关联容器 集合set
[STL] 12.关联容器 映射map
[STL] 13.关联容器 多重集合multiset
[STL] 14.关联容器 多重映射multimap
[STL] 15.关联容器 无序集合unordered_set(C++ 11)
[STL] 16.关联容器 无序集合unordered_map(C++ 11)
[STL] 17.仿函数functor与函数对象
[STL] 18.预定义函数对象、仿函数适配器
[STL] 19.算法algorithm
[STL] 20.迭代器适配器
[STL] 21.空间配置器allocator
1. 什么是STL?
标准模板库 - 维基百科,自由的百科全书 (wikipedia.org)
标准模板库(英文:Standard Template Library,缩写:STL),是一个C++软件库,大量影响了C++标准程序库但并非是其的一部分。其中包含4个组件,分别为算法、容器、函数、迭代器。[1]
模板是C++程序设计语言中的一个重要特征,而标准模板库正是基于此特征。标准模板库使得C++编程语言在有了同Java一样强大的类库的同时,保有了更大的可扩展性。
2. STL的优势
- 功能强大、代码精致
STL由惠普实验室的无数大牛们开发,设计精巧,功能强大,集成了优秀的算法。
- 高可重用性
ST广泛使用模板泛型编程,代码具有高度的复用性。
- 高性能、工业强度
ST提供的算法具有工业强度,高性能,用它可开发出性能高效的应用程序。
- 开源跨平台
STL跨平台,而且开源,开发者可以很容易借鉴与扩展。
3. STL版本?
HP STL
HP STL是Alexandar Stepanov在惠普Palo Alto实验室工作时,与Meng Lee合作完成的。HP STL是C++ STL的第一个实现版本,而且是开放源码。其它版本的C++ STL一般是以HP STL为蓝本实现出来的。
SGI STL
由Silicon Graphics Computer Systems公司参照HP STL实现,主要设计者仍然是STL之父Alexandar Stepanov,被Linux的C++编译器GCC所采用。SGI STL是开源软件,源码可读性甚高。
STLport
为了使SGI STL的基本代码都适用于VC++和C++ Builder等多种编译器,俄国人Boris Fomitchev建立了一个free项目来开发STLport,此版本STL是开放源码的。
P.J.Plauger STL
由P.J.Plauger参照HP STL实现出来,被Visual C++编译器所采用,但不是开源的。
Rouge Wave STL
由Rouge Wave公司参照HP STL实现,用于Borland C++编译器中,这个版本的STL也不是开源的。
4. STL的六大组件
1、容器(Containers):各种数据结构,如Vector,List,Deque,Set,Map,用来存放数据,STL容器是一种Class Template,就体积而言,这一部分很像冰山载海面的比率。
2、算法(Algorithms):各种常用算法如Sort,Search,Copy,Erase,从实现的角度来看,STL算法是一种Function Templates。
3、迭代器(Iterators):扮演容器与算法之间的胶合剂,是所谓的“泛型指针”,共有五种类型,以及其它衍生变化,从实现的角度来看,迭代器是一种将:Operators*,Operator->,Operator++,Operator–等相关操作予以重载的Class Template。所有STL容器都附带有自己专属的迭代器——是的,只有容器设计者才知道如何遍历自己的元素,原生指针(Native pointer)也是一种迭代器。
4、仿函数(Functors): 行为类似函数,可作为算法的某种策略(Policy),从实现的角度来看,仿函数是一种重载了Operator()的Class 或 Class Template。一般函数指针可视为狭义的仿函数。
5、配接器(适配器)(Adapters):一种用来修饰容器(Containers)或仿函数(Functors)或迭代器(Iterators)接口的东西,例如:STL提供的Queue和Stack,虽然看似容器,其实只能算是一种容器配接器,因为 它们的底部完全借助Deque,所有操作有底层的Deque供应。改变Functor接口者,称为Function Adapter;改变Container接口者,称为Container Adapter;改变Iterator接口者,称为Iterator Adapter。配接器的实现技术很难一言蔽之,必须逐一分析。
6、分配器(Allocators):负责空间配置与管理,从实现的角度来看,配置器是一个实现了动态空间配置、空间管理、空间释放的Class Template。
——《STL源码剖析》
5. 学习建议
路线:
- C++数据结构
- C++模板
- STL标准库
- Boost库
资源:
Containers - C++ Reference (cplusplus.com)
cppreference.com
6. 为什么需要迭代器?
#include "stdafx.h"
#include<iostream>
using namespace std;/* 思考题一
现在有一个数组 int arr[5] = { 1,2,3,4,5 };
void Print(int *begin, int *end)
{
//此处编写代码
}
让 Print(arr, arr + 5); 实现打印所有元素?
*//*
void Print(int *begin, int *end)
{//此处编写代码for (int *p = begin; p != end; ++p)//利用指针的++,依次访问每个元素{cout << *p << " ";}cout << endl;
}
*//* 思考题二现在有一个链表,有5个Node节点:struct Node
{
int data;
Node* next;
};void Print(Node *begin, Node *end)
{
//此处编写代码
}让 Print(pHead, pTail ); 实现打印所有元素?
*/struct Node
{int data;Node* next;
};ostream & operator <<(ostream& o,const Node &node)
{o << node.data << endl;return o;
}/*
void Print(Node *begin, Node *end)
{//此处编写代码for (Node *p =begin; p!= end ; p=p->next) //指向下一个节点{cout << (*p).data << " "; }cout << endl;
}
*///思考题三
//写出一个通用的Print 函数模板
template<class T>
void Print(T begin, T end)
{//此处编写代码for (T p = begin; p != end; ++p){cout << *p << " ";}cout << endl;
}int main()
{//题目一测试int arr[5] = { 1,2,3,4,5 };Print(arr, arr + 5); //arr + 5是指向 最后一个元素下一个的位置//Print<int *>(arr, arr + 5);//调用模板函数//题目二测试Node n1;n1.data = 11;Node n2;n2.data =22;Node n3;n3.data = 33;Node n4;n4.data = 44;Node n5;n5.data = 55;n1.next = &n2;n2.next = &n3;n3.next = &n4;n4.next = &n5;n5.next = NULL;Print(&n1, n5.next);return 0;
}
7. 自己实现迭代器iterator
迭代器(iterator)是指针的抽象,它允许程序员以相同的方式处理不同的数据结构(容器)。
迭代器支持的一些基本操作:
=
:迭代器赋值==
:比较迭代器的相等性!=
:比较迭代器的不等性++
:迭代器向后移动--
:迭代器向前移动*
:解引用,返回迭代器指向的元素
#include "stdafx.h"
#include<iostream>
using namespace std;//思考题三
//写出一个通用的Print 函数模板
template<class T>
void Print(T begin, T end)
{//此处编写代码for (T p = begin; p != end; ++p){cout << *p << " ";}cout << endl;
}//虽然数组不需要迭代器,因为指针就是一种特殊的迭代器
//也可以设计一个数组迭代器
class ArrayIterator
{public:ArrayIterator(int *p) : _p(p) {}ArrayIterator & operator++(){ ++_p;//指针就是++指向下一个return *this ;}bool operator!=(const ArrayIterator & it){return _p != it._p;}int& operator*(){return *_p;}//private: int * _p;
};//考虑设计一个中间类,让它支持operator ++,实际实现是链表的p=p->next
//链表迭代器
class ListIterator
{public:ListIterator(Node *p) : _p(p) {} ListIterator & operator++(){//链表的真正操作_p = _p->next;return *this;}bool operator!=(const ListIterator & it){return _p != it._p;}Node& operator*( ){return *_p;}
//private: Node * _p;
};int main()
{//使用链表迭代器ListIterator begin(&n1);ListIterator end(n5.next);Print(begin, end);return 0;
}
8. STL中的5种迭代器
- 输入迭代器(Input iterator)
- 输出迭代器(Output Iterator)
- 前向迭代器(Forward iterator)
- 双向迭代器(Bidirectional iterator)
- 随机访问迭代器(Random Access iterator)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-on3WXlhN-1620021492142)(C:\Users\tangx\AppData\Roaming\Typora\typora-user-images\image-20210503133856493.png)]
不同的数据结构(容器)支持的迭代器类型不同,比如数组结构可支持随机访问迭代器,但是链表结构就无法支持,链表往往设计为双向迭代器。
9. STL中的iterator类
iterator
类是一个基类模板,可用于从它派生迭代器类。它不提供迭代器具有的任何功能,仅提供了些默认成员类型,这些并不是迭代器类型必须需具备的,它们可能是有用的。
定义:
iterator - C++ Reference (cplusplus.com)
template <class Category, class T, class Distance = ptrdiff_t,class Pointer = T*, class Reference = T&>struct iterator {typedef T value_type;typedef Distance difference_type;typedef Pointer pointer;typedef Reference reference;typedef Category iterator_category;};
Category
迭代器所属的类别。 它必须是以下迭代器标签之一:
迭代器标签 | 迭代器的类别 | 迭代器类型 |
---|---|---|
input_iterator_tag | Input Iterator | 输入迭代器 |
output_iterator_tag | Output Iterator | 输出迭代器 |
forward_iterator_tag | Forward Iterator | 前向迭代器 |
bidirectional_iterator_tag | Bidirectional Iterator | 双向迭代器 |
random_access_iterator_tag | Random-access Iterator | 随机访问迭代器 |
T
迭代器指向的元素类型。
Distance
键入以表示两个迭代器之间的差异。
Pointer
类型,表示指向迭代器指向的元素的指针。
Reference
类型,表示对迭代器指向的元素的引用。
示例代码:
#include "stdafx.h"
#include<iostream>
#include<iterator>using namespace std;class A
{public:typedef int MYINT; //内部类型using MYFLOAT = float; //内部类型
};class MyIterator : public std::iterator<std::random_access_iterator_tag, int>
{int* p;
public:MyIterator(int* x) :p(x) {}MyIterator(const MyIterator& mit) : p(mit.p) {}MyIterator& operator++() { ++p; return *this; }MyIterator operator++(int) { MyIterator tmp(*this); operator++(); return tmp; }bool operator==(const MyIterator& rhs) const { return p == rhs.p; }bool operator!=(const MyIterator& rhs) const { return p != rhs.p; }int& operator*() { return *p; }//int &operator[](int index) { return *(p + index); }
};int main()
{//A::MYINT a = 100;//A::MYFLOAT b = 100;//定义一个迭代器对象iterator< input_iterator_tag , int> it ;//内部类型:iterator_category代表迭代器类别类型cout << typeid(iterator<input_iterator_tag, int>::iterator_category).name() << endl;//迭代器指向元素的类型cout << typeid( iterator<input_iterator_tag, int>::value_type).name() << endl;//迭代器指向元素的指针类型cout << typeid(iterator<input_iterator_tag, int>::pointer).name() << endl;//迭代器指向元素的引用类型 cout << typeid(iterator<input_iterator_tag, int>::reference).name() << endl;//迭代器指向元素的指针类型 相减得到的差值类型cout << typeid(iterator<input_iterator_tag, int>::difference_type).name() << endl;iterator<input_iterator_tag, int>::value_type a = 100;iterator<input_iterator_tag, int>::pointer pA = &a;iterator<input_iterator_tag, int>::reference b=a;cout << a << " " << *pA << endl;b = 200;cout << a<<" "<< b << endl;iterator<input_iterator_tag, int>::pointer pB = &a+2;iterator<input_iterator_tag, int>::difference_type c = pB - pA;cout << c << endl;//测试自定义的迭代器int numbers[] = { 10,20,30,40,50 };MyIterator from(numbers);MyIterator until(numbers + 5);for (MyIterator it = from; it != until; it++)std::cout << *it << ' ';std::cout << '\n';//cout << from[3] << endl;MyIterator::value_type x = 100;return 0;
}
10. 序列容器对比
序列容器 | 数据结构 | 底层实现 | 迭代器 | 优缺点 |
---|---|---|---|---|
array (c++11)
|
固定数组 | 普通数组、连续内存 | 随机访问迭代器 | 快速随机访问、在中间插入、删除元素效率较低、无法扩容 |
vector
|
动态数组 |
new 堆内存 、连续内存
|
随机访问迭代器 | 快速随机访问、在中间插入、删除元素效率较低、容量可动态增长 |
deque
|
双端队列 | 一个中央控制器和多个缓冲区、不连续 | 随机访问迭代器 | 快速随机访问、两端插入、删除效率高 |
list
|
双向链表 | 双向链表、不连续 | 双向迭代器 | 不支持随机访问、可双向遍历、任意位置插入、删除元素效率高 |
forward_list (c++11)
|
单向链表 | 单向链表、不连续 | 前向迭代器 | 不支持随机访问、单向遍历、任意位置插入、删除元素效率高 |
11. 容器适配器对比
容器适配器 | 数据结构 | 底层实现 | 迭代器 | 特点 |
---|---|---|---|---|
stack
|
栈 |
底层默认用queue 实现,也可以是vector 、list
|
不支持 | 先进后出 FILO |
queue
|
队列 |
底层默认用queue 实现,也可以是list
|
不支持 | 先进先出 FIFO |
priority_queue
|
优先队列 |
底层默认用vector 为容器,使用堆heap 为处理规则来排序。容器也可以是deque
|
不支持 | 优先级最高(或最低)的元素先出 |
12. 关联容器对比
序列容器 | 数据结构 | 底层实现 | 迭代器 | 优缺点 |
---|---|---|---|---|
set
|
集合 | 红黑树 | 双向迭代器 | key唯一、有序 |
map
|
映射 | 红黑树 | 双向迭代器 | key唯一、有序、value可重复 |
multiset
|
多重集合 | 红黑树 | 双向迭代器 | key可重复、有序 |
multimap
|
多重映射 | 红黑树 | 双向迭代器 | key可重复、有序、value可重复 |
unordered_set
|
无序集合 | 哈希表 | 双向迭代器 | key唯一、无序 |
unordered_map
|
无序映射 | 哈希表 | 双向迭代器 | key唯一、无序、value可重复 |
unordered_multiset (c++11)
|
无序多重集合 | 哈希表 | 双向迭代器 | key可重复、无序 |
unordered_multimap (c++11)
|
无序多重映射 | 哈希表 | 双向迭代器 | key可重复、无序、value可重复 |
C++ STL标准模板库简介相关推荐
- 【C++】STL(标准模板库)简介
STL简介 文章目录 STL简介 什么是STL STL版本 STL的六大组件 如何学习STL STL的缺陷 什么是STL STL(standard template libaray-标准模板库):是C ...
- 19.3 C++STL标准模板库大局观-容器的说明和简单应用例续
19.1 C++STL标准模板库大局观-STL总述.发展史.组成与数据结构谈 19.2 C++STL标准模板库大局观-容器分类与array.vector容器精解 19.3 C++STL标准模板库大局观 ...
- 19.1 C++STL标准模板库大局观-STL总述、发展史、组成与数据结构谈
19.1 C++STL标准模板库大局观-STL总述.发展史.组成与数据结构谈 19.2 C++STL标准模板库大局观-容器分类与array.vector容器精解 19.3 C++STL标准模板库大局观 ...
- 【跟学C++】C++STL标准模板库——算法详细整理(下)(Study18)
文章目录 1.简介 2.STL算法分类及常用函数 2.2.变序算法(二) 2.2.1 替换算法(2个) 2.2.2 排序算法(6个) 2.2.3 分区算法(4个) 2.2.4 可用于排序容器的算法(3 ...
- C++提高编程----STL标准模板库-常用容器
STL标准模板库(Standard Template Library)-常用容器 C++的,面向对象和泛型编程,目的就是提高代码的复用性:为了建立数据结构和算法的统一标准,诞生了STL 一.STL初识 ...
- STL(标准模板库)理论基础与容器
10.1 STL(标准模板库)理论基础 10.1.1基本概念 STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称.现然主要出现在C++中,但在被 ...
- 【跟学C++】C++STL标准模板库——算法详细整理(中)(Study18)
文章目录 1.简介 2.STL算法分类及常用函数 2.1.变序算法(一) 2.2.1 初始化算法(2个) 2.2.2 修改算法(2个) 2.2.3 复制算法(6个) 2.2.4 删除算法(6个) 3. ...
- 补8-5日复习内容 STL 标准模板库的容器
//有关 STL 标准模板库的函数 /* string 的 */ /* #include <iostream> #include <string> #include <w ...
- stl标准模板库_C ++标准模板库(STL)中的array :: fill()
stl标准模板库 fill() is a member function of "array container", which sets a given value to all ...
最新文章
- 解决报错:Can't read private key和./build-aux/cksum-schema-check: Permission denied
- python待遇如何-老男孩学Python后就业如何?Python待遇高吗?
- 【一周入门MySQL—2】单表查询
- Intel处理器CPUID指令学习
- HCIE-Security Day11:双机热备,从VRRP到VGMP
- python-常用模块-time、datetime模块
- 思科模拟器之工大瑞普版(u7)下载地址
- pta C语言选择题
- 提升生产力,7 款好用的原型图工具推荐给你
- 华三路由交换配置命令_h3c路由器配置命令
- Android 和风天气+腾讯地图
- 深圳高中女生街头版someone like you
- 利用python画分形图_「分形」python简单的分形图片 - seo实验室
- linux中日志服务器的搭建
- 中科院计算机控制学院难度,16年自动化所复试失败经验
- win7 svchost.exe 占用内存cpu过高
- MAC电脑配置maven
- DirectX11 With Windows SDK--11 混合状态
- DAE向春秋航空公司交付三架新型A320飞机中的第一架
- html 字前边自动加点,css实现文字越界加点点点显示,并且后面紧跟一个图标
热门文章
- 猿来小课web前端介绍html语言基础学习
- LoRa模块(内置MCU),亿百特E22-400T30S,广播监听、定点传输、中继组网
- 苹果wifi网速慢怎么办_WiFi用着用着就断了?这样设置WiFi永不断网,大部分人不知道...
- 微信公众号引流源码?基本上没啥用!
- smart200+步进控制
- repo (一) 简介
- 为什么选择0.1uF电容而不是0.01uF电容?
- 【c++】VSCode配置 c++ 环境(小白教程)
- python找完数 pta_PTA——完全数
- php创建网址打不开,php网站无法打开怎么办