10.1 概述
- 大多数算法定义在algorithm中,标准库还在头文件numeric中定义了数值泛型算法
- 一般情况下,这些算法并不直接操作容器,而是遍历由两个迭代器指定的一个元素范围来进行操作。
find(迭代器1.cbegin(),迭代器2.cend(),元素);
当不能找到时,返回迭代器2.- 由于指针就像内置数组上的迭代器一样,使用标准库中的begin和end来获得数组中首元素和尾元素的指针也可以在数组中查找:
find(begin(arr),end(arr),元素);# 10.2 初始泛型算法
算法如何工作
迭代器令算法不依赖与容器,。。。。
。。。。,但算法依赖于元素类型的操作
10.2 初始泛型算法
- 除了少数例外,标准库算法都对一个范围内的元素进行操作。称此范围为输入范围
- 理解算法最基本的方法就是了解他们是否读取元素,改变元素,重排元素
10.2.1 只读算法
- 例如find函数和count函数
- accumulate函数(begin,end,和的初值).
accumulate的第三个参数的类型决定了函数中使用那个加法运算符已经返回值的类型
算法和元素类型
操作两个序列的算法
equal
:接受三个迭代器,前两个表示第一个序列中的元素范围,第三个表示第二个序列的首元素- 由于利用迭代器完成操作,因此我们可以通过调用equal来比较不同类型的容器中的元素。元素类型可以不必一样,只要我们能用==来比较两个元素类型即可。例如string和const char*
那些只接受一个单一迭代器来表示第二个序列的算法,都假定第二个序列至少与第一个序列一样长
- equal(roster1.cbegin(),roster1.cend(),roster2.cbegin());
如果roster都是C分格的字符串即const char *则用==比较两个char对象,只是检查两个指针值是否相等,即地址是否相等而不是其中字符是否相同
10.2.2 写容器元素的算法
- 算法不会执行容器操作,因此他们自身不可能改变容器的大小
算法不检查写操作
- fill_n:写入指定元素
介绍back_inster
拷贝算法
课后题
list<int> ilst = {1,2,3,4};
fill_n(ilst.begin(), ilst.size(), 0);
- a程序中进行缺省初始化,但是vec为空,copy无法进行,如需改变容器大小,需要使用一类特殊的称为插入器的迭代器。将第三个参数改为back_insterter(vec);
10.2.3 重排容器元素的算法
10.3 定制操作
10.3.1 向算法传递函数
谓词
- 是一个可调用的表达式,其返回结果是一个能用作条件的值
10.3.2 lambda表达式
- 尾置返回 auto GetType() -> int;
向lambda传递参数
- lambada不能有默认参数
使用捕获列表
- 一个labbda通过即将局部变量包含在其捕获列表中来指出将会使用这些变量。
- 一个lambda只有在其捕获列表中捕获一个它所在函数中的局部变量,才能在函数中使用该变量
for_each算法
10.3.3 lambda捕获和返回
- 当定义一个lambda时,编译器生成一个与lambda对应的新的(未命名的)类类型。可以这样理解,当向一个函数传递一个lambda时,同时定义了一个新类型和该类型的一个对象。
值捕获
- 采用值捕获的前提是变量可以拷贝。与参数不同,被捕获的变量的值是在lambda创建时拷贝,而不是调用时拷贝。
引用捕获
- 采用引用捕获必须确保被引用的对象在lambda执行的时候是存在的。lambda捕获的都是局部变量,这些变量在函数结束之后就不存在了。
- 我们也可以从一个函数返回一个lambda。但此lambda不能包含引用捕获
隐式捕获
- 为了指示编译器推断捕获列表,应在捕获列表中写一个&或=。前者告诉编译器采用捕获引用方式,后者表示采用值捕获方式。
可变lambda
指定lambda返回类型
10.3.4 参数绑定
绑定check_size的sz参数
使用placeholders名字
bind参数
用bind重排参数顺序
绑定引用参数
10.4 再探迭代器
10.4.1 插入迭代器
10.4.2 iostream迭代器
istream_iterator操作
使用算法操作流迭代器
istream_iterator允许使用懒惰求值
ostream_iterator操作
使用流迭代器处理类类型
10.4.3 使用反向迭代器
反向迭代器需要递减运算符
反向迭代器与其他迭代器之间的关系