1 STL组建(STL Components)
关键组建:容器,迭代器,算法
STL的基本观念就是将数据和操作分离,数据由容器类加以管理,操作则由可定制的算法定义之, 迭代器在两者之间充当粘合剂,使任何算法都可以和任何容器交互运作
2 容器(Containers)和迭代器
迭代器的分类:
1 双向迭代器:
可以双向进行,以递增运算前进或以递减运算符后退(list set multiset map multimap 均提供此类迭代器)
2随机存期迭代器:
随机存取迭代器具备双向迭代器的所有有属性还具备随机访问能力:vector deque string
3之间差异:
只有随机访问迭代器才支持operation <<; 所以代码一般会写成第一种
容器相关函数:
reverse()将区间能元素翻转
coll2.resize(coll.size());// 改变coll2元素个数
dequecoll3(coll1.size());初始化时指明要有的足够空间
六迭代器之配接器:
(一)三种迭代器配接器:
1 Insert iterators(安插型迭代器)
2stream iterators(流迭代器)
3Reverse iterators(逆向迭代器)
安插型迭代器:
Inset iterators 可以使算法以安插的方式而非覆写方式运作可以解决算法的“目标空间不足” 的问题是的它会促使目标区间的大小按需要成长
如果对某个元素设值会引发所属群集的安插操作,至于插入位置在容器的最前还是最后或是某个指定位置上,需要视三种情况而定:
(1) 单步前进不造成任何动静
1.1 Back inserters(安插于容器最尾端)
Back inseters 内部调用push_back()在容器尾端插入元素
For(pos=coll.begin();pos!=coll.end();++pos) { ………………… } For(pos=coll.begin();pos
Copy(coll1.begin(),coll1.end(),back_inserter(coll2)
(只有vector deque list提供push_back())
2.2 Front Inserters(安插于容器最前端)
Copy(coll1.begin(),coll1.end(),front_inserter(coll3));
这种动作逆转了被安插元素的次序如果先安插1再向前安插2那么1会在2后边提供push_front的容器只有:deque list
2.3 Generalinerters(一般性安插器):
一般性的inserters它的作用是将元素插入初始化时接受第二个参数的位置的前方inserters 内部调用成员函数insert()并以新值和新位置做参数所有STL容器都提供insert()函数
(2)Stream Iterator(流迭代器)
copy(istream_iterator(cin),istream_iterator(),back_inserter(coll));
sort(coll.begin(),coll.end());
unique_copy(coll.begin(),coll.end(),ostream_iterator(cout,"\n"));
2.1istream_iterator(cin)
这个产生一个可从标准输入流cin读取数据的streamiterator
2.2 istream_iterator()
调用istreamiterator 的default构造函数产生一个代表”流结束”符号的迭代器它表示你不能在从中读取任何东西
2.3 ostream_iterator(cout,”\n”)
产生一个output stream iterator,透过operator<< 向cout写入strings第二个参数作为元素之间分割符
(2) Reverse Iterator(逆向迭代器)
逆向方式进行操作
所有容器都可以通过成员函数rbegin()和rend()产生出reverse iterator
(二)更易型算法(manipulatingalgorithm删除或重排或修改元素的算法)
1 算法remove()自某个区间删除元素
for(inti=1;i<=6;++i)
{
coll.push_front(i);
coll.push_back(i);
}
remove(coll.begin(),coll.end(),3);
结果:654211245656
数值为3删除后被其后元素覆盖,至于群集尾端那些违背覆盖的元素,原封不动但从逻辑上说,那些元素已经不属于这个群集了
改进:
List::iterator end=remove(coll.begin(),coll.end(),3)
copy(coll.begin()end,ostream_iterator(cout,","));
结果:6542112456
或者采用:
Distance(end,coll.end());
Distance()是返回两个迭代器之间的距离
如果真想把删除的元素斩草除根你必须调用该容器的相应成员函数容器提供成员函数erase()适用此目的erase()可以删除“ 参数所指示区间”内的全部元素
2更易型算法和相关容器
Erase()成员函数返回删除元素的个数
(三)以函数作为算法的参数
void print(intelem)
{
cout<
}
for_each(coll.begin(),coll.end(),print);
2判断式(predicate)
所谓predicate就是返回布尔值的函数他们通常用来指定排序规则和搜索准则,并非任何返回bool值得一元函数或二元函数就是合法的predicate STL要求面对相同的值predicate必须得出相同的结果,这条戒律将那些“被调用时会改变自己内部状态的函数排除了”
3仿函数(functors,FunctionObject即函数对象)
传递给算法的“函数参数”不一定是函数,可以是行为类似函数的对象
仿函数的优点:
(1) 智能型含糊 smart point
仿函数可拥有成员函数和成员变量这意味着仿函数拥有状态,其次你可以在初始时初始化他们,当然必须在他们被调用之前
(2) 仿函数都有自己的型别(可以设计函数继承体系)
(3) 仿函数比一般函数要快
预定义的仿函数:
Setcoll;会被扩展为set>coll;
所以反向排列这些元素可以是set>coll;
透过一些特殊函数配接器你可以将预定义的仿函数和其它数值组合到一起或使用特殊状况
例如:
Transform(coll.begin(), coll.end(),back_inserter(coll2),bind2d(mltiiplies(),10)
将coll中的所有元素乘以10后安插到coll2中这里使用配接器使得multiple运算时以源群集的元素作为第一个参数,10作为第二个参数
仿函数一般声明为:inline
特殊仿函数:
For_each(coll.begin(),coll.end(),mem_fun_ref(&Person::save());
仿函数mem_fun_ref用来调用他所作用的元素的某个成员函数
(四)容器内的元素
1 容器元素的条件
(1)必须可以通过copy构造函数进行复制, copy函数的性能尽可能优化
(2)必须可以透过assignment操作符完成赋值操作(即=号)
(3)必须可以通过析构函数完成销毁动作析构函数决不能设计成preivate
析构函数决不能抛出异常
(4) 对于序列式容器而言,元素的default构造函数必须可用
(5) 对于某些动作必须定义operatpor==以执行相等测试
(6)在关联式容器中元素必须定义排序准则缺省情况下operator<透过仿函数less<>调用