5 STL组件

5 STL组件

5.2 容器

序列式容器:排列次序与置入次序一致,vector、deque、list。

关联式容器:元素位置取决于特定的排序规则,set、multiset、map、multimap。

容器适配器:stack,queue,priority queue。


vector:dynamic array,尾部添加或移除元素非常快速,但在中部或头部安插较慢。

deque:双向dynamic array,尾部或头部安插都很快。

list:双向链表,不提供随机存取,所以元素存取会花费线性时间。

*string:与vector类似,只是元素为字符。

*array:非STL容器,无size(),empty()等成员函数,但可针对array调用STL算法。


set:元素自动排序,元素值不允许重复。

map:可被视为关联式数组,每个键只能出现一次。


5.3 迭代器

end()指向最后一个元素之后,“逾尾迭代器”,或容器为空,则begin()等于end()。

list<char>::const_iterator pos;这种迭代器以只读模式遍历元素,即可以++pos,但不能改变*pos。(注意++pos比pos++效率高。)

multimap<int, string> coll;
coll.insert(make_pair(3,"abc"));

//map还可以以这种方式插入元素,因为键值唯一
map<string, float> coll2;
coll2["Pi"] = 3.14;

分类:STL迭代器只属以下两类:

双向迭代器:list、set、multiset、map、multimap的迭代器。

随机存取迭代器:(具备双向迭代器的所有属性)vector、deque、string的迭代器。

 

5.4 算法——<algorithm>

泛型函数式编程思维模式(数据与操作相分离),与OOP相悖。

1、区间

所有算法处理的都是半开区间。(确定哪个迭代器在前的方法P99-100)

 

2、多个区间处理

如copy(coll1.begin(), coll1.end(), coll2.begin());将第一区间内的全部元素拷贝到第二区间(注意不是insert),需要保证第二区间内有足够的空间,不然会出错。

为了避免错误,(1)确定目标区间有足够的元素空间(如使用coll2.resize(coll.size();或者vector<int> coll2(coll1.size())直接初始化其大小),(2)使用insert iterator。

 

5.5 iterator adapaters(迭代器配接器——特殊迭代器)

1、insert iterator——可用于解决多区间目标空间不足的问题。

copy(coll1.begin(), coll1.end(), back_inserter(coll2));   //安插于容器尾端,排列次序与安插次序相同
copy(coll1.begin(), coll1.end(), front_inserter(coll2));  //安插于容器前端,排列次序与安插次序相反
copy(coll1.begin(), coll1.end(), inserter(coll2, pos));   //在pos的前一个元素上安插,,排列次序与安插次序相同

2、流迭代器stream iterator

vector<string> coll;
copy(istream_iterator<string>(cin), istream_iterator<string>(), back_insertor(coll));
sort(coll.begin(), coll.end());
uniqe_copy(coll.begin(), coll.end(), ostream_iterator<string>(cout, "\n");
//uniqe_copy()消除毗邻的重复值,"\n"为输出分隔符


3、逆向迭代器reverse iterator

copy(coll.rbegin(), coll.rend(), ostream_iterator<string>(cout, "\n");
//coll.begin()指向最后一个元素,coll.rend()指向第一个元素前一个位置。

 

5.6 变动型算法(Manipulation Algorithm)

指那些会移除remove,重排resort,修改modify元素的算法。

1、注意:迭代器对自己所属的容器一无所知。任何“以迭代器访问容器元素”的算法,都不能通过迭代器调用容器类别所提供的任何成员函数。

//假设coll为1 2 3 4 5 6
//移除value 3
remove(coll.begin(), coll.end(), 3);
//结果coll为1 2 4 5 6 6,coll.size()未发生变化,因为remove不会调用erase(),不会产生coll.erase(remove(coll.begin(),coll.end(),3), coll.end());的效果。remove()的返回值为修改后的逻辑终点,即1 2 4 5 6后一个位置。

 

2、无法用于关联式容器

变动型算法会修改某位置上的值,进而破坏其已序特性。

 

3、优先使用成员函数

例:对于list,list.remove(4)比算法remove(coll.begin(), coll.end(), 4);效率高,因为前者利用了list的链表特性,并且直接删除,而已知后者对size无影响。

 

5.7 可以自定义泛型函数

5.8 以函数作为算法参数

void print(int elem){...}

vector<int>coll;
for_each(coll.begin(), coll.end(), print);

//for_each()定义
template<class Iterator, class Operation>
Opreration for_each(Iterator act, Iterator end, Operation op)
{
	while(act != end){
		op(*act);++act;
	}
	return op;
}


5.9 仿函数——函数对象

行为类似于函数的对象。

class PrintInt{
public:
	void operator()(int elem) const{cout<<elem<<' ';}
};

vector<int>coll;
for_each(coll.begin(), coll.end(), PrintInt()); //PrintInt()产生一个临时对象,for_each中PrintInt op; op(*act)相当于op.operator()(*act)  


 1、特性

仿函数是智能型函数;每个仿函数都有自己的类型;仿函数通常比一般函数速度快(仿函数可以有自己的状态)。

 

2、预定义仿函数

transform(coll1.begin(), coll1.end(), back_inserter(coll2), bind2nd(multiplies<int>(), 10));
//将coll1中元素乘10后插入coll2
//bind2nd使得进行multiples运算时,以源元素为第一参数,10为第二参数

repalace_if(coll2.begin(), coll2.end(), bind2nd(equal_to<int>(), 70), 42);


5.10 容器中的元素

1、条件:

必须可通过copy构造函数进行复制;必须课通过assignment操作符完成赋值;必须可通过析构函数完成销毁(析构函数不能抛出异常)。

应当满足条件:序列式容器 的default构造函数可用;对于某些动作,定义operator==以执行相等测试;关联式容器中,元素必须定义出排序准则(缺省为operator<)。

 

2、STL只支持value语义。(使用智能指针可实现reference语义,但不能用auto_ptr,见P222。)

 

5.11 STL内部的错误处理和异常处理

1、几乎不进行错误处理。(STLport是一个安全版本的STL,可用于软件开发阶段。)

2、基本保证(发生异常时,不会发生资源泄露,也不会与容器的恒常特性想抵触)+部分强保证(异常发生时,不产生任何影响)

    对“以节点为实现基础”的容器(set,map等),如果节点构造失败,容器保持不变。移除节点的动作保证不会失败。对于关联式容器插入单一元素支持commit-or-rollback(交付或回复),但是插入多个元素则不能保证。

    对于“以array为构造基础”的容器安插元素失败无法恢复,但是push和pop在尾端执行,可以做到强保证。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值