STL 标准模板库(Standard Template Libarary)是为许多标准数据结构和算法提供泛型程序的C++库。STL提供3种类型的组件:容器、迭代器和算法,它们都支持泛型程序设计
标准。
库是使用模板建立的,在设计上是高度正交(orthogona)的。正交是指库中的组件可以结合起来作用于本地类型和用户提供的类型,这可以通过对STL中的各种元素进行正确的实例化实现。本章只是STL的概述和简要介绍。STL非常庞大,也很复杂,许多新系统对STL进行了更重要的深度扩展。
7.1 一个简单STL示例
现在从一个使用容器类vector的例子开始。在6.6.2节中曾经简要讨论过容器类vector,它是C++中本地数组类型的泛化,所以很容易理解和使用。事实上,STL的一种最有效的使用方法就是使用STL的向量代替普通的C++数组。相对于数组来说,STL的vector类型有许多重要的优点,例如动态扩展,因此可以避免溢出。另外,它还可以很容易地使用迭代器和索引进行遍历,而且它还有丰富的内置操作接口。
文件 stl_vector1.cpp
// Simple STL vector program
#include <iostream>
#include <vector>
using namespace std;
int main ()
{
vector<int> v(100); // 100 is vector's size
for (int i = 0; i < 100; ++i)
v[i] = i;
for (vector<int>::iterator p = v.begin();
p != v.end(); ++p)
cout << *p << '\t';
cout << endl;
}
stl_vector程序解析
■ // Simple STL vector program
#include <iostream>
#include <vector>
using namespace std;
vector库包含了组件vector<>的STL模板。
■ vector<int> v(100); // 100 is vector's size
STL容器vector用于替代一个普通的int型数组。与其他模板一样,它使用一个已经存在的类型进行实例化,这里使用了本地类型int。模板类有一组构造函数,这里使用的构造函数创建了一个长度为100的int vector。
■ for (int i = 0; i < 100; ++i)
v[i] = i;
第一条for语句的写法与C++中作用于普通数据的for循环的写法完全相同。在大多数实例中,除了声明之外,无需修改任何代码,向量就可以替代本地数组。
■ for (vector<int>::iterator p = v.begin();
p != v.end(); ++p)
cout << *p << '\t';
第二条for语句使用了迭代器p。迭代器就像一个指针,STL提供了成员函数begin()和end()作为容器的起始和终止位置值。注意,end()返回的迭代器位置(或地址)是容器最后一个元素的后一个位置。因此,end()是一个警戒位置,或者说是一个信号值,它可以提示你已经结束了对容器的遍历。
下一个例子使用了list容器、迭代器和泛型算法accumulate()。这里需要使用list和numeric库。
文件 stl_container.cpp
#include <iostream>
#include <list> // list container
#include <numeric> // for accumulate
using namespace std;
// Using the list container
void print(list<double> &lst)
{
list<double>::iterator p; // traverse iterator
for (p = lst.begin(); p != lst.end(); ++p)
cout << *p << '\t';
cout << endl;
}
int main()
{
double w[4] = { 0.9, 0.8, 88, -99.99 };
list<double> z;
for (int i = 0; i < 4; ++i)
z.push_front(w[i]);
print(z);
z.sort();
print(z);
cout << "sum is "
<< accumulate(z.begin(), z.end(), 0.0)
<< endl;
}
在这个例子中,实例化后的list容器用来存储double型数值。一个double型数组被压入list,函数print()使用一个迭代器依次打印list的每个元素。注意,迭代器就像指针一样工作。list和vector都有标准的begin()和end()成员函数提供容器的开始和结束位置,list的接口还包括一个稳定(stable)排序算法,即成员函数sort()。在稳定排序算法中,相等的元素保留原来的相对位置。accumulate()函数是numeric包中的一个泛型函数,它使用0.0作为初值,并且通过从开始位置z.begin()遍历到最末警戒位置z.end()计算list容器中元素的总和。
注意,将print()函数进行参数化会使算法更加通用,方法是使用迭代器区间,以及指示打印退出位置的返回值。下面编写这个函数:
// Using the iterator range
// b is the beginning location
// e is the guard location and ends the iteration
template <class Iterator>
Iterator print(Iterator b, Iterator e)
{
for (Iterator p = b; p != e; ++p)
cout << *p << '\t';
cout << endl;
return p; //guard value
}
这个print()函数更加通用,它能作用在所有标准容器上,包括基本数组类型。它也说明了STL使用的一些习惯,一种比较典型的情况是:最末位置是警戒值并且是最后一个被处理的元素的下一个位置。因此,循环终止测试是p!=e,这样就不再处理该位置。







