STL(Standard Template Library)简介
STL是c++标准的一个组成部分,具有效率和易用性。
STL的组成部分
容器是STL的核心,用来存储和组织数据。配置器是为容器服务的,复制其内存空间的分配和管理。迭代器是为算法服务的,算法通过迭代器访问容器中的数据。函数对象也是为算法服务的,通过配置不同的函数对象,可以改变算法的计算策略。适配器通过对已有的容器、迭代器和函数对象的改造,可以创造出新的编程组件。
示例代码
这里添加代码
#include <cstdlib>
#include <iostream>
#include <vector> // 包含容器 vector 的头文件
#include <algorithm> // 包含算法头文件
using namespace std; // 使用名称空间 std
template<class T>
struct Print // 定义一个 Print 结构,作为函数对象来使用
{
void operator()(T& x) const // 重载括号()运算符
{
if( x % 2 == 0 ) // 如果参数是偶数
{
cout<<x<<' '; // 输出参数
}
}
};
int main(int argc, char *argv[]) // 主函数
{
cout<<"——使用 STL——"<<endl;
cout<<endl;
vector<int> vcInts; // 实例化一个 vector 容器
for(int i = 0; i < 10; ++i) // 将整数 0 到 9 插入到容器中
{
vcInts.push_back(i);
}
vector<int>::iterator iterBegin, iterEnd; // 定义两个迭代器
iterBegin = vcInts.begin(); // 指向容器的开始
iterEnd = vcInts.end(); // 指向容器的结尾
cout<<"输出所有元素:"<<endl;
for(; iterBegin != iterEnd; ++iterBegin) // 用迭代器遍历整个容器
{
cout << *iterBegin << " "; // 输出容器中的各个元素
}
cout << endl;
cout<<"输出偶数元素:"<<endl;
iterBegin = vcInts.begin(); // 重新指向容器的开始
for_each(iterBegin, iterEnd, Print<int>());
// 通过算法 for_each 和函数对象 Print 输出容器中的元素
cout<<endl<<endl;
return EXIT_SUCCESS; // 主函数返回
}
由于代码重载了括号运算符(),所以可以当作一个函数对象使用。函数中定义了一个只存放int型数据的vector容器对象。程序最后调用for_each算法,并结合使用了函数对象print、for_each的行为类似于for循环。
容器的分类
容器(containers),顾名思义,就是用来装东西的。程序中的容器是指用来储存和组织数据的数据结构。为了支持泛型编程,这种数据结构应当写成模板类,所以在STL中所谓的容器就是各种类模板。
STL 容器基本上都支持容量的自动增长。添加数据时,如果容量不能满足要求,
容器就会自动分配新的内存,以用来容纳添加的数据。
按照储存方式分类,容器可以分为序列式容器和关联式容器。所谓序列式容器,是指元素依照加入的顺序进行排序。所谓关联式容器,是指元素都是两部分组成的,分为键值(key)和实值(value)。键值和实值之间存在对应关系。当数据加入到容器中时,按照键值进行排序,因此关联式容器是自动有序的。
序列式容器有两种存储方式。一种是连续存储,即容器中相邻元素的存储单元是连续的,新加入的元素总是放在最后一个元素的下一个存储单元中,数组就是这样一种连续存储的序列式容器。另外一种方式是链式存储,即相邻元素的存储单元不是连续的,而是用某种方式将其连接在一个,可以在元素中用一个(或多个)指针,指向相邻元素存储单元的地址,或者用整数表示相邻元素的存储索引。 关联式容器也有两种存储方式。一种是使用搜索二叉树,容器中的元素依照其键值进行排序。另外一种是利用哈希表,容器中的元素按照其键值,根据哈希算法安置在不同的存储单元中。 标准STL是用红黑树来实现关联式容器的。红黑树是一种查找效率更高的平衡搜索二叉树。
容器的常用方法
容器是用来存储数据的,因此容器一般具有如下方法:
1.初始化(容器、初始值、元素的比较方法等)
2.数据的增删查改。
3.容器的数据统计(容器大小、元素数目)
初始化容器
容器的初始化是在容器构造时完成的。初始化的内容包括容量、初始值、元素的比较方法等。一般来讲,序列式容器要求初始化容器,而关联式容器(基于红黑树的)要求初始化元素的比较方法。对于基于哈希表实现的关联式容器也要求初始化容量。
这里添加代码
vector<int> vec( 12 ); // 构造整型向量,初始容量 12
list<int> lst( 34 ); // 构造整型链表,初始容量 34
struct ltstr // 重载了括号运算符的函数对象
{
bool operator()(const char* s1, const char* s2) const
{
return strcmp(s1, s2) < 0;
}
};
map<const char *, int > strIntMap( ltstr() );
// 构造字符串到整型的映射,初始化键值比较方法为 ltstr
set<const char *> strSet( ltstr() );
// 构造字符串集合,初始化键值比较方法为 ltstr
两种类型的容器都可以在构造时设置初始值,初始值是用两个迭代器对象所标识的容器区间,新容器中的元素被初始化这个容器区间的值。
这里添加代码
int ary1[5] = {1, 2, 3, 4, 5}; // 整型数组
vector<int> vec( ary1, ary1+5 ); // 用数组初始化向量
list<int> intList( vec.begin(), vec.end() ); // 用向量初始化链表
set<int> intSet( list.begin(), list.end() ); // 用链表初始化集合
数组也是一种容器,由c++编译器预定义。vector和list的成员函数begin和end返回的是容器的迭代器,分别指示的容器的头和尾