STL 简介
STL(标准模板库)是一个可复用组件库,也是一个包算法与数据结构的软件框架. STL 在 1994 年走入C++标准,使得原本即将推出的C++标准延迟4 年问世, 由于STL 包含很多高效稳定的数据结构与算法, 所以在程序开发人员中得到了广泛的使用 . STL 的实现版本主要有五种,分别为 HP 实现版本,P.J.Plauger 实现版本,Rouge Wave 实现版本,STLport 实现版本,SGI STL 实现版本,它们所提供的功能一样,只是版权及代码的风格不同。
STL 主要分容器,算法, 迭代器三大块。容器与迭代器是以类的形式提供,容器类包含很多数据结构及其上的操作.算法是一些常用的操作的集合,包含排序,查找,拷贝,数学运算等. 迭代器是 STL 的关键部分,它在容器与算法之间起桥梁作用, 类似于 C 语言中的指 针, 但比指针复杂。
容器,算法,迭代器
1 容器
STL 的容器主要有两种分类方式,一种是按容器的规范来分,可分为标准容器与非标准容器。另一种可按照容器内部的存储特性来分,可分为序列式容器与关联式容器。所以 STL 容器一般分为以下四类:
标准 STL 序列容器:vector, string, deque 和list。
标准 STL 关联容器:set, multiset, map 和multimap。
非标准序列容器: slist 和rope。
非标准的关联容器hash_set,hash_multiset. hash_map 和hash_multimap。
2 算法
STL 的算法也主要有两种分类方式,一种是按是否改变容器中无素内容来分,可分为质变算法与非质变算法.另一种是按操作的对象可分为数值算法,基本算法,set相关算法,heap 算法, 常用操作算法。下面以第三种分类法介绍 STL 的算法:
数值算法:accumute, adjacent_difference, inner_product, partial_sum, power, iota。
基本算法: equal, fill, fill_n, iter_swap, lexicographical_compare, max, min, mismatch,
swap, copy, copy_backward.。
Set 相关算法有 set_union, set_intersection, set_difference, set_symmetric_difference.
Heap 算法有 make_heap, pop_heap, push_heap, sort_heap
常用操作算法有:adjacent_find, count, count_if, find, find_if, find_end, find_first_of, for_each, generate, generate_n, includes, max_element, merge, min_element, partition, remove, remove_copy, remove_if, remove_copy_if, replace, replace_copy, replace_if, replace_copy_if, reverse, reverse_copy, rotate, rotate_copy, search, search_n, swap_ranges, transform, unique, unique_copy, lower_bound, upper_bound, binary_search, next_permutation, prev_permutation,
random_shuffle, partial_sort, partial_sort_copy.等
3 迭代器
迭代器是一种行为类似指针的对象, 而指针的各种行为中最常见也最重要的便是内容提领和成员访问.因些迭代器重要编程工作就是对 operator*和 operator->进行重载工作 迭代器的主要内容就是迭代器型别, 迭代器的型别有五种:value type, difference type, reference, iterator category.第一种型别 value type 表示迭代器所指类型的类型.第二种型别 Difference type 表示两个迭代器之间的距离的类型. 第三种型别reference type表示是否可改变所指对象的内容.第四种类型表示所指之物的地址的类型.第五种类型表示迭代器的类型,这个反映了迭代器的特性。
STL 的应用
STL 中全是模板的实现方式,所以使用时要特化, 指明类型. 对于一般层次的程序员来说, 平时使用较多的是容器。容器也成为程序员的主要帮手。下面介绍一下一些容器,迭代器,算法的特性。
vector
Vector 容器就像 C 语言中的数组, 其元素存放在连续的空间里,但它的空间是可以动态伸缩的,即随着元素的增加而增加.这一点上又不同于普通的数组。
Vector 的的常用成员函数有 begin, end, size, capacity, empty, front, back, push_back ,
pop_back, erase, resize, clear, 这些含盖了 vector的基本操作.
Vector支持随机存取,所以 vector支持的是 random access iterator。就像数组在程序设计中的广泛性一样,程序员在使用 STL 时,vector 容器也是程序员常用的一种容器。
map
map 是一种关联式容器.它是键-值对的集合.map 类型通常可理解为关联数组:可使用键作为下标来获取一个值, 正如内置数组类型一样.而关联的本质在于元素的值与某个特定的键相关联, 而并非通过元素在数组中的位置来获取。
map所有元素都会根据元素的键值自动被排序.map的所有元素都是pair, 同时拥有实值(value)和键值(key).pair 的第一元素被视为键值, 第二元素被视为实值.map 不允许两个元素拥有相同的键值。
map 的常见操作有 key_comp, value_comp, begin, end, rbegin, rend, empty, size, max_size, swap, insert, erase, clear, find, count, lower_bound, upper_bound, equal_range。因为 map 的每个元素都是一个键值对,所以可来存放更多的信息,且效率高,所以也是程序员常用的容器之一。
iterator, const_iterator, reverse_iterator以及 const_reverse_iterator
STL 中的所有标准容器都提供了 4 种迭代器类型.对容器类 container<T>而言,iterator类型的功效相当于 T*, 而 const_iterator 则相当于 const T*.对一个 iterator 或者 const_iterator进行递增则可以移动到容器中的下一个元素, 通过这种方式可以从容器的头部一直遍历到尾部.reverse_iterator 与const_reverse_iterator同样分别对应于 T*和const T*, 所不同的是,对这两个迭代器进行递 增的效果是由容器的尾部反向遍历容器头部。
图 1 反映了4 种 iterator之间的转换关系.箭头表示转化关系.从中可以发现不能从 const_iterator转化为iterator, 也不能从const_reverse_iterator转化为reverse_iterator.以为选迭代器的类型时优先选择 iterator,以免类型无法相互匹配。
find 算法
find 算法是 STL 中较为常见的一种算法,它是循环查找一个区间[first, last]内的所有元素, 找出第一个与待查元素相等的元素.如果找到,就返回一个 inputiterator 指向该元素, 否则返回迭代器 last.其函数原型为:
template <class InputIterator, class T>
inputIterator find(InputIterator first, InputIterator last, const T& value);
for_each 算法
for_each的函数原型为 template <class InputIterator, class Function>
function for_each(InputIterator first, InputIterator last, Function f);
此函数 f会施行于[first, last]区间内的每一个元素身上。F不可以改变元素内容, 因为 first和 last 都是 InputIterators,不保证接受赋值行为,
copy 算法
copy的函数原型为
template <class InputIterator, class OutputIterator>
inline OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result)
copy 是一个常常被调用的函数。由于 copy 进行的是复制操作,而复制操作不外乎运用assignment operator或copy constructor, 但是某些元素型别拥有的是trivial assignment operator, 因些能够使用内存直接复制行为(比如 c 中的 memmove 或 memcpy), 便能够节省大量时间 。
STL的应用行业
STL 作为一种通用的程序组件库,几乎任何行业都能应用它来提高开发效率, STL 已广泛应用在通信行业,网络游戏, windows 与 linux应用程序设计中, 大大提高了开发的时间,而且这些稳定的组件库的应用, 相比自已亲手写的函数来说, 在稳定性与可移植性方面要 好很多。比如在通信及网络游戏行业中, map 可用来存放套接字和地址元素对, 这样也便于查找, 在实际中的效果好.而 copy算法常用在消息包的组合与解析之中,用起来非常方便, 不和自已重新开发。 比如在搜索行业,哈希表与红黑树就用得较好,这些容器本身实现就非常复杂,查找效率很高。如果是自已开发这些东西的话,仅仅手工实现这数据结构就要花很多时间, 更不谈手工实现的代码的稳定性了,而且如果不稳定的话,组后期的维护也带来了麻烦。由此可看出 STL 的重要性了
较常用的容器 vector, list, stack, pair会广泛用来各个行业之中,而常用算法 find, for_each,count, reverse, sort, search也是常用在日常程序设计之。
一个实例
程序分为服务器端, 客户端, 控制端三个部分,服务器与客户关可以互通基本消息,而控制端则控制服务器向客户端的消息发送.对于客户端, 控制台与服务器端的连接及 ip 地址,可用 map 来保存, 对于连接的查找可用 find 来查找。
服务器的存入链接与 ip的变量定义为:
map<int, string> sockip;
控制台发送一个含有客户端 ip 的消息到服务器后(此 ip 的变量为 srcip, 可使用 map 的基
本操作查找此 ip 的客户端与服务器的套接字,从而可以向客户端发送消息. 查找的代码为:
iterator first = sockip.begin();
iterator last = sockip.end();
for(;first!=last&&first->second!=srcip;first ++)
客户端的姓名与 ip 的变量定义为:
Map<string, string> nameip;
可通过 find 算法查找是否 nameip 中是否有些用户, 从而判断该客户是否在线,
查找的代码为
iterator first = nameip.begin();
iterator last = nameip.end();
iterator clientiterator = find(first, last, make_pair(srcname, strip));
还可使用 for_each 在输出在线客户的姓名,地址信息.
template <class T>
struct display<map<string, string>>{
void operator()(const T& x)
{
cout << x.first << “ ”<< x.second << endl;;
}
}
iterator first = nameip.begin();
iterator last = nameip.end();
for_each(first, last, display<map<string, string>>);
总结
本文开始介绍了 STL 的三大主要部分容器,算法,迭代器基本知识和特性,接着分析了STL 的常用容器,算法,迭代器的使用方式及范围,最后通过一个实例介始了在实际编程中使用 STL 的方法.这样就能更加深刻地认识 STL 的基本理论及使用方法.STL 作为一个 C++中重要的一部分,学习 STL 也成为程序员的一门重要的课程。