STL-迭代器和traits编程技法


迭代器

1.什么是迭代器,迭代器有什么用

迭代器提供了对容器中对象的访问方法,它使算法独立于具体容器存在,解决了算法思想相同,却因容器元素访问方法不同导致需要实现多个版本算法的问题。举个例子find算法,对于listvector来说,它接受的参数和返回值,甚至是内部实现都是一样的,但是list这个容器的结构是一个双向链表;而vector却是一个数组。照理来说由于链表和数组的访问元素的方法不同,我们需要实现多个与具体容器对应的find算法,但是由于迭代器的存在,我们现在只需要实现一个版本的find算法就行了。也就是说,迭代器使算法独立于具体容器而存在。

2.迭代器的分类

a. (前向+只能用于读出数据)输入迭代器:只读,支持++==!=

b. (前向+只能用于写入数据)输出迭代器:只写,支持++

c. 前向迭代器:即输入迭代器+输出迭代器

d. 双向迭代器:前向迭代器+后向操作(--)【stl容器的迭代器都是双向迭代器其以上】

e. 随机访问迭代器:除了双向迭代器提供的自增++和自减--外,还提供[n]+n等随机访问的功能

例子:setmap这种用红黑树实现的,也就是说不是连续内存的,就是双向迭代器,所以它们的不可能支持+n[n]的操作。而vectorstringdeque)这种整块内存的,一般就是随机访问迭代器了,支持+n[n]操作。当然也有stackqueuepriority_queue这种因为容器本身的特性,而不支持迭代器的情况出现。

3.迭代器失效(主要还是随机访问迭代器的连续内存)

迭代器失效是指,迭代器原来所指向的元素不存在或者移动了,此时如果不更新迭代器,将无法使用该过时的迭代器达到想要的结果。

a. Vector迭代器失效(随机访问迭代器,整块内存)

a) Push_back操作:vector内存满时,用push_back,导致容器扩容,所有内容搬移,导致原来迭代器失效。

b) Erase操作:擦除vector中间的某个对象,后面元素拷贝覆盖前面元素,导致原先迭代器失效。

c) Resize操作:扩容,导致元素整体拷贝,原先迭代器失效。

d) Swap操作:被交换对象的迭代器失效

e) 赋值运算操作:被赋值容器的迭代器全部失效

b. Deque迭代器失效(随机访问迭代器,多块连续内存)

a) 插入操作:在双端队列的队首和队尾插入不会导致迭代器失效;而在中间插入会(回想一下双端队列的内存布局)

b) 删除操作:队首队尾的删除操作只会导致,被删除的元素的迭代器失效。中间删除会导致其他元素的迭代器失效。

c. List/set/map迭代器失效(双向迭代器)

a) 只有被删除元素的迭代器失效(回想一下内存布局,都是链表,删除某个节点并不影响到其他节点)

4.迭代器、模板偏特化与traits编程技法

a) 模板特化与偏特化:

i. (类模板特化与偏特化)与(普通版本)的不同之处在于类名之后的尖括号<>中,进一步加了限制条件;(特化)与(偏特化)的不同之处在于template后的<>中是不是有参数。

ii. 其执行机制是这样的:当实例化一个模板时,编译器会把目前存在的所有偏特化和特化,泛化版本做一下比较,找出其中最合适、最匹配的实现

b) 所谓的traits编程技法:

i. 给普通迭代器写个类型萃取 再给原生指针写个偏特化版的类型萃取


这样不管是T是类类型的迭代器还是原始指针,我们都可以这么写了:

Template<class I>
Typename iterator_traits<I>::valtype function(I ite){
	Return *ite;
}

ii. 所谓traits编程技法,就是在有多个模板版本的情况下,又包了个类,向使用者提供了同一接口。


模板偏特化这边,复习的时候仍需要看一下课本,此处不够详尽


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值