Boolan_STL与泛型编程_第四周笔记

本周课程主要内容为STL6大部件中的迭代器算法泛函数适配器。其中算法与其他STL部件的区别之一是算法是函数模板,其他的是类模板。

1、各部件的关系

图1.1

STL的6大部件是相互联系的。算法虽然对容器一无所知,但是它通过问答迭代器,通过迭代器实现了对容器的操作。当迭代器无法回答迭代器的问题时,编译就会报错。算法也是泛函数的应用场合之一。适配器则是在容器、迭代器、泛函数的基础上再次封装,用这三大部件实现所需功能。

2、迭代器

本节主要分两部分:iterator_category和iterator_category对算法的影响。

2.1 iterator_category

共有五种迭代器类型,其中input——farward——bidirectional——random_access,从右向左是依次继承的关系,还有一种单独的类型为output_iterator。

图2.1
图2.2
图2.3

本小节内容小结如下:

(1)使用随机访问迭代器的容器:array, vector,deque;

使用双向迭代器的容器:list,红黑树作为底层支撑的容器;

使用单向迭代器的容器:forward_list;

两个特殊的迭代器类型:input迭代器(istream_iterator)和output迭代器(ostream_iterator);

(2)五种迭代器均是class,是通过迭代器的萃取器来得到类型;

(3)istream_iterator和ostream_iterator的迭代器种类的格式相同,G2.9版中有两个模板参数,G3.3和G4.9版本中有四个模板参数。

2.2  iterator_category对算法的影响

图2.4
图2.5
图2.6
图2.7

本小节内容小结如下:

(1)distance:计算两个迭代器间的距离时,内部首先会识别iterator的类型,之后根据不同的迭代器类型调用不同的__distance(first, second, category())函数计算距离,category()是个临时对象,表示iterator的类型;

(2)若可以直接相减则选用上述图2.4中的方法2,尾-头,速度快;若不能直接相减则选用上述图2.4中的方法1,一步一步走,计算总共走多少步;

(3)advance:实现iterator移动n个元素的位置时,其内部会调用__advance(i, n, iterator_category(i)), iterator_category函数用于获取iterator的类型,根据不同的迭代器类型调用不同的__advance函数,如图2.5所示,有3中情况,如果是input迭代器,那么会将iterator逐个移动n个位置;如果是双向迭代器,那么会先判断n是正整数还是负整数,再决定是向前还是向后逐个移动;如果是随机访问迭代器,那么直接将指针加n个位置;

(4)在调用distance,advance等这类重载的函数时,如果没有特别对这种迭代器类型的实现函数,那么会根据迭代器类型的父类找到重载的函数,例如,若iterator是forward_iterator_tag,返回类型为inline,用方法1(原因为forward_iterator_tag继承input);

(5)copy:实现复制内容时,内部有多出检查,首先会检查first和last的类型,如果是const char类型,那么会调用memmove();如果是const wchar_t类型,那么也会调用memmove();如果是InputIterator类型,那么就调用__copy_dispatch(),再去判断是const T, 还是T,还是迭代器,如果是迭代器,那么会再去检查是随机的还是其他类型的迭代器,如果是指针类型,那么会利用type traits询问它的拷贝构造重不重要(has trivial op=(), has non-trivial op=(),对于不需要自己定义,可以使用编译器给的默认拷贝构造函数,才叫做不重要的拷贝构造);

(6)destroy和copy类似,都是会将传入的类型做判断,不同的类型采用不同的处理方式;

(7)unique_copy:(first, last, result)函数中result如果是outputIterator,由于output iterator无法read, 无法执行result !=first, 对于这种情况的处理就不同于result传入的是forward iterator。

3、算法

总共介绍了12种算法,包括算法accumulate、算法for_each、算法replace,replace_if,replace_copy、算法count,cout_copy、算法find,find_if、算法sort以及算法binary_search。

图3.1
图3.2
图3.3
图3.4
图3.5
图3.6
图3.7
图3.8

本节内容总结如下:

(1)accumulate(first, last, init),元素直接相加;

accumulate(first, last, init, binary_op), 元素累计,binary_op可以传自定义的函数,或是泛函数,binary_op(init,first)这个函数定义了初值init和first之间的计算方法;

(2)replace()是将first到last内等于old_value的元素替换为new_value;

replace_if()这里predicate表示要传一个能返回真假的判断函数pred(*first), 返回真的话,会做替换;

replace_copy()是将将first到last区间内的值拷贝给res, 如果是old_value,替换为new_value再拷贝给res,原有的值不做替换;

(3)count(first, last, value) 对于其中等于value的元素进行计数;

count_if(first, last, pred) 对于其中符合pred(*first)的元素进行计数.;

如果容器中有自己的版本,要用自己的,效率更高;

(4)sort(first, last, op); op可以是自定义比较大小的函数,也可以是泛函数;

sort要求容器可跳跃,而list和forword_list不能跳跃;

(5)r.begin()和r.end()是通过reverse iterator实现的。

4、仿函数

总共分为三大类仿函数:算术类、逻辑运算类和相对关系类。标准库提供的仿函数都有继承关系。

图4.1
图4.2
图4.3

本节内容总结如下:

(1)identify、select1st、select2nd是GUN C++独有的仿函数,是非标准的,identify传入什么元素就传出什么元素,select1st传入pair, 传出pair中第一个元素,select2nd传入pair, 传出pair中第二个元素;

G4.9版本中名称有所改变,_Identify、_Select1st、_Select2nd;

(2)3种仿函数的共同点:都是继承自unary_function或是binary_function类,他们内部定义了一些typedef, 共适配器询问,他们的内部并没有数据成员,对于自定义的泛函数只有遵循STL的体系架构,继承于unary_function或是binary_function才能作为泛函数适配器。

5、适配器

适配器可以改造泛函数、迭代器和容器。适配器中可以拥有泛函数、迭代器或容器。

图5.1
图5.2
图5.3
图5.4
图5.5
图5.6

本节内容总结如下:

(1)A改造B,A需要取用B的功能,有两种实现方法:A继承B或者A拥有B,适配器中使用的是A拥有B这种方法;

(2)binder2nd(泛函数适配器):2nd指第二参数,bind2nd(less(), 40)给less函数绑定第二个参数为40,使得第一个参数和40进行比较,这里less()是一个临时对象,并没有被调用 ;

(3) not1(泛函数适配器):not1(pred), 对pred的结果取非;

(4)bind (新型适配器):C++11标准中才有,可以绑定函数、泛函、成员函数(_1必须是某个object地址)、数据成员(_1必须是某个object地址);

(5)inserter(迭代器适配器):是函数模板,将元素插入到另一个容器中。copy(bar.begin(), bar.end(), inserter(foo, it)); 将bar的元素全部插入到foo容器的it位置,并不覆盖foo原有的元素,如果是copy(bar.begin(), bar.end(), foo.begin());这样写会覆盖foo中原有的元素;

(6)ostream_iterator(X适配器,三大类之外的适配器):其内部定义了拷贝赋值函数,将value赋值给标准输出,所以copy会调用ostream_iterator的拷贝赋值,输出各个元素;

ostream_iterator相当于count(输出),istream_iterator相当于cin(输入)。

6、课堂难点知识理解

(1)inserter

C++ 语言提供了三种插入器,其差别在于插入元素的位置不同。

back_inserter,创建使用push_back实现插入的迭代器。

front_inserter,使用push_front实现插入。

inserter,使用insert实现插入操作。

也许有人认为可使用inserter和容器的begin迭代器来模拟front_inserter的效果。然而,inserter的行为与front_inserter的有很大差别。在使用front_inserter时,元素始终在容器的第一个元素前面插入。而使用inserter时,元素则在指定位置前面插入。即使此指定位置初始化为容器中的第一个元素,但是,一旦在该位置前插入一个新元素后,插入位置就不再是容器的首元素了。

(2)ostream_iterator

ostream_iterator是流迭代器,流迭代器是标准模板库中的,因此是类模板。

ostream_iterator<int>指定了类型,就是迭代器读写的类型。通过这个流迭代器可以把你要输入的写入到指定的流中。cout就是指定的流,就是标准输出。可以改成一个输出流就可以,比如一个文件。通俗的一点说,你把它看成一个指向输出流的指针,通过这个指针你可以把东西写的输出流中。

copy (v.begin(),v.end(),output);这个意思就是说,把向量V中的数据放到cout输出流中,通过流迭代器output.

ostream_iterator output(cout ,"*");这个的意思说,放到输出流的时候,没放一个整数,就末尾添加一个*.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容