C++primer 第10章 泛型算法

10.1概述

迭代器算法不会依赖容器,体现其泛型,但算法会依赖元素类型的操作,如排序算法sort默认使用<运算符,当然可以用运算符重载来自定义,或者使用sort的带谓词的重载版本,通过函数指针实现自定义。

算法永远不会执行容器的操作,只会对迭代器操作,从而导致算法永远不会改变底层容器的大小,算法可能改变容器中保存的元素,也可能在容器中移动元素,但永远不会直接添加或删减元素( 笔者猜测这可能是迭代器支持的运算符决定的,而默认情况下的迭代器不会具有添加和删除功能,之后我们学习的插入迭代器,通过重载迭代器支持的‘=’运算符使其具有插入功能。)

10.2初始泛型算法

  • 泛型算法结构
    输入迭代器:只读,不写;单遍扫描,只能递增
    输出迭代器:只写,不读;单遍扫描,只能递增
    前向迭代器:可读写;多遍扫描,只能递增
    双向迭代器:可读写;多变扫描,可递增递减
    随机访问迭代器:可读写;多遍扫描,支持全部迭代器运算
    除了输出迭代器之外,一个高层类别的跌大气支持低层类别的迭代器的所有操作,c++标准指明了泛型和数值算法的每个迭代器参数的最小类别

  • 输入迭代器

支持:

  • 用于比较两个迭代器的相等和不相等(==,!=)
  • 用于推进迭代器的前置和后置递增操作
  • 用于读取元素的解引用运算符(*)
  • ->运算符,提取对象成员
    输入迭代器只能用于顺序访问,对于一个输入迭代器,*it++保证是有效的,但递增它可能导致其他指向流的迭代器失效(因为流管理一个缓冲区,迭代器递增,会导致原先位置失效),其结果就是,不能保证输入迭代器的状态可以保存下来,因此只能用于单遍扫描;显然istram_iterator是一种输入迭代器。
  • 输出迭代器

支持:
用于推进迭代器的前置和后置递增操作
解引用运算符(*),向一个解引用额输出迭代器赋值,就是将值写入它所指向的元素
只能向输出迭代器复制一次,所以只能单遍扫描,ostream_iterator类型是输出迭代器。

  • 前向迭代器

只能向一个方向移动,但是可以多次读写同一个元素,所以可以保存前向迭代器的状态,forward_list上的迭代器是前向迭代器。

  • 双向迭代器

可以正向反向读写序列中的元素,reverse要求双向迭代器。

  • 随机访问迭代器

除了支持双向迭代器的所有功能,还支持:

  • 用于比较两个迭代器相对位置的关系运算符(<,>,<=,>=)
  • 迭代器和一个整数的加减运算,计算结果是迭代器在序列中前进或后退的给定运算后的位置
  • 用于两个迭代器上的减法运算符-,得到两个迭代器的距离
  • 下标运算符(iter[n]),与*(iter[n])等价
    顺序存储的容器的迭代器,访问内置数组的元素的指针也是

特别值得注意的是:向目标迭代器写入数据,算法都是假定目标空间能够容纳写入的数据,如果是指向容器的迭代器,则使用绑定容器的插入迭代器或是一个ostream_iterator


几种特殊的迭代器

  • 插入迭代器

it=t :在it指定的位置插入值t,插入前需绑定容器,,根据迭代器的类型的不同,在赋值时调用push_back,push_front,insert
注意:*it,++it,it++,这些操作虽然存在,只是为了保持使用的一致性,但是不会对it做任何事情,每个操作都返回It,这个可以通过运算符重载实现
类型
back_inserter:创建一个使用push_back的迭代器
front_inserter:创建一个使用push_front的迭代器
inserter:创建一个使用insert的迭代器,有两个参数,这个参数必须是一个指向给定容器的迭代器,元素被插入给定元素之前
当然,只有容器有相应的操作,插入迭代器才能绑定。

  • 流迭代器

isteam_iterator
istream_iterator要读取的类型必须定义了输入运算符,创建时可以绑co定一个流,默认初始化时,创建了一个可以当作尾后值使用的迭代器
下面是一个从标准输入读取数据,存入一个vector的例子:

istream_iterator<int> int_iter(cin);//从cin读取int
istream_iterator<int> int_eof;//istream尾后迭代器
whihe(int_it!=int_eof)
{
vec.push_back(*iter++);
}

C++标准库中的实现保证的是,在第一次的解引用迭代器之前,从流中读取数据的操作已经完成,这导致值得注意的是如果我们创建了一个istream-iterator,没有使用就销毁了,或者我们正在从两个不同的对象同步读取一个流,合适读取可能就很重要了。

ostream_iterator
我们可以对任何具有输出运算符(<<运算符)的类型定>ostream_iterator。
当创建一个ostream_iterator时,我们可以提供(可选的)第二参数,它是一个字符串,在输出每个元素后都会打印此字符串。此字符串必须是一个C风格字符串(即,一个字符串字面值常量或者一个指向以空字符结尾的字符数组指针)。必须将ostream_iterator绑定到一个指定的流,不允许空的或表示尾后位置的ostream_iterator。

  • 反向迭代器

普通迭代器和反向迭代器均反映左闭合区间,为了实现表示相同的范围
[c.rbegin,rit)和[it.base,it.end),导致it.base和rit必须是相邻而不是相等,也导致了一个结果:用一个普通


10.3算法定制操作

算法会有接受谓词的版本,在排序算法中,自定义比较大小函数,例如sort(begin,end,compare),在查找或者替换算法中,自定义相等函数find_if(begin,end,if)


lambda表达式

引入lambda表达式可以解决泛型算法只能接受一元谓词和二元谓词(谓词是一个可调用表达式,其返回结果是一个能用作条件的值)的问题,当然也可以使用bind函数,达到同样的目的,当定义一个lambda表达式时,编译器生成一个lambda对应的新的未命名的类类型,目前可以这样理解,当向一个函数传递了一个lambda表达式,同时定义了一个新类型,和该类型都包含了一个的一个对象,传递的参数卆编译器生成的类类型的未命名的可调用对象,默认情况下,从lambda生成的类都包含了捕获列表中变量对应的数据成员,当然创建时,数据成员拷贝初始化。

lambda表达式形式:
[capture list](parameter list) ->return type{ function body}

可以忽略参数列表和返回类型,当未指定返回类型,如果函数体只有一个return语句,可根据函数体中的代码分析返回类型,否则返回类型为void,捕获列表只用于局部非static变量,lambda可以直接使用局部static变量和它所在函数之外声明的名字;

捕获方式有值捕获,引用捕获;
隐式捕获,编译器自己根据函数体内推断使用了哪些变量,[=]表示值捕获,[&]表示引用捕获,还可以混合使用隐式捕,显示获和显示捕获,捕获列表中的一个元素必须是=或&,显示捕获的变量捕获方式必须和隐式捕获不同

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

推荐阅读更多精彩内容