STL是C++中重要部分之一(面向对象、STL、模板等),其中三个基本的STL组件包括:
1. 迭代器。迭代器之于容器相当于指针之于数组,提供了访问容器对象的方法,事实上C++中的指针也是一种迭代器,但是要注意迭代器不仅仅是指针,不一定具有地址值。
2. 容器。容器是一种模板类,例如list、vector、deques等,一般由迭代器访问容器中的数据。
3. 算法。STL中数据结构和算法是分离的,各种函数在广义容器中(包括链表、数组、string对象、容器)完全通用。
1.头文件:
STL头文件一般不使用.h扩展,其中主要使用的头文件和对应容器类如下:
#include Container Class
<deque> deque
<list> list
<map> map, multimap
<queue> queue, priority_queue
<set> set, multiset
<stack> stack
<vector> vector
<string> string
<iterator> ***<***>::iterator
<algorithm> 各种算法函数
STL均使用标准命名空间using namespace std。
2.迭代器:
迭代器有五种类型,这五种类型是一种继承关系,具体如下:
Input iterators:提供对数据的只读访问,前向推进。输入迭代器可以使用==和!=来测试是否相等;使用*来访问数据;使用++操作符前向推进。例如find函数需要保证输入迭代器。
Output iterators:提供对数据的只写访问,前向推进。输出迭代器缺省只写,由于该迭代器无法读取对象,因此不会在任何搜索和其他算法中使用它。
Forward iterators:提供读写访问,前向推进。例如replace函数需要保证前向迭代器。
Bidirectional iterators:提供读写访问,前向或后向推进。例如reverse函数需要保证双向迭代器。
Random access iterators:提供读写访问,随机移动(非const的指针也是随机迭代器)。STL中的排序和搜索函数使用随机访问迭代器,随机访问迭代器可以使用关系操作符做比较。
除此之外,还包括一些特殊的迭代器:
指针迭代器:一个指针也是一种迭代器。
常量迭代器:对于只读变量,为了防止错误赋值,可以使用常量迭代器const_iterator,该迭代器指向的对象不允许改变。注意:const ***<***>::iterator的含义是该迭代器成为常量,不可指向其他数据,与常量迭代器的含义是不一样的。
3.流迭代器
将输入输出(例如标准输入输出流cin/cout或者文件流等)作为容器看待,因此接受迭代器参数的算法都可以和流一起工作。
STL定义模板类ostream_iterator作为输出流迭代器,其构造函数有两个参数,包括一个ostream对象和一个string值(作为间隔符),因此可以象下面一样创建一个迭代器:
ostream_iterator<int>(cout, “/t”) //定义cout迭代器
ofstream out(“text.txt”);
ostream_iterator<string> obegin(out, “/n”); //定义文件流输出迭代器
STL定义模板类istream_iterator作为输入流迭代器,可指定读取的来源,并应该和结束迭代器比较。具体如下:
istream_iterator<int> intreader(cin); //定义cin流迭代器
isteam_iterator<int> eof;
copy(istream_iterator<string>(cin), istream_iterator<string>(), 输出迭代器); //定义无变量名的cin流迭代器
ifstream in(“text.txt”);
istream_iterator<string> ibegin(in);
istream_iterator<string> iend; //定义文件流输入迭代器
还有一些具体应用如下:
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/2f88ce130b654eb5dc6788e02dbcfc90.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0ac3a2d53663ec01c7f7225264eeefae.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/2f88ce130b654eb5dc6788e02dbcfc90.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0ac3a2d53663ec01c7f7225264eeefae.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/2f88ce130b654eb5dc6788e02dbcfc90.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/df37983f39daa189b8c814e01a6a9011.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0ac3a2d53663ec01c7f7225264eeefae.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
注意:上面用输入流迭代器来初始化vector后,不可再用这个输入流迭代器,因为随着数据的读取,迭代器已经到达输入流或者文件流的末尾了。
4.插入迭代器:
int arr[] = {1, 2, 3, 4, 5};
vector<int> vi;
copy(arr, arr + 5; vi.begin());
该语句不会执行,因为没有为vi分配存储空间。此时使用插入迭代器可以将值插入到容器中,自动为vi扩展存储空间,主要包括三种插入迭代器。
普通插入器:将对象插入到容器任何对象的前面。该迭代器使用容器的insert操作符替代赋值运算符,第一个参数是容器本身,第二个参数是容器迭代器指定插入位置。
Front inserters:将对象插入到数据集的前面,例如链表表头。该迭代器使用push_front操作替代赋值运算符,参数是容器本身。
Back inserters:将对象插入到数据集的尾部,例如vector的尾部,导致vector容器扩展。该迭代器调用容器的push_back操作替代赋值运算符,参数是容器本身。
注意:使用插入迭代器可能导致容器中的其他对象移动位置,因此现有的迭代器变成非法,需要重新赋值(list除外,不受影响)。
![](https://i-blog.csdnimg.cn/blog_migrate/2f88ce130b654eb5dc6788e02dbcfc90.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/cbef093dcc044b2793832001e2365e43.gif)
5.混合迭代器函数:
下面两个迭代器函数非常有用:
advance(iterator, int):按照指定的数目增减迭代器。第一个参数是迭代器,第二个参数是增减的数目(前向迭代器该数必须为正,双向或者随机迭代器该数可以为负)。
distance(iterator, iterator, int&):返回到达一个迭代器所需递增操作的数目。该函数是递归的,每次递归第三个参数,因此必须初始化该参数为0然后使用该函数。