C++ primer超详细讲解泛型算法
初识泛型算法
只读算法
只读取输入范围内的函数,不改变元素,find,accumula也是如此
(1)accumulate算法为求和算法,前两个参数指出求和元素范围,第三个是和的初值,例:
int sum=accumulate(v.begin(),v.end(),0)
(2)操作两个序列的算法
equal算法,确定两个序列是否保存相同的值,将第一个序列的每个元素和第二个序列中的每个元素进行比较,若相同返回true,否则返回false,接受三个参数,前两个表示第一个序列的元素范围,第三个表示第二个序列的首元素
equal(r1.begin(),r1.end(),r2.begin())
写容器算法
(1)拷贝算法
向另一个目的位置迭代器指向的输出序列中的元素写入数据算法。此算法接受三个迭代器,前两个表示一个舒服范围,第三个表示目的序列的起始位置。copy返回目的迭代器的值。
1 2 3 |
|
定制操作
lambda表达式
(1)定义
一个lambda表达式表示一个可调用的代码单元,可理解为未命名的内联函数
lambda表达式形式:
[capture list](parameter list) - > return type{function body}
可以忽略参数列表和返回类型,但必须永远包含捕获列表和函数体
auto f =[] {return 42}
调用: cout<<f()<<endl;
(2)向lambda传递参数
实参被用来初始化lambda的形参,lambda不能有默认参数
例:
1 2 3 |
|
(3)使用捕获列表
一个lambda通过将局部变量包含在其捕获列表中指出将会使用这些变量,捕获列表指引lambda在其内部包含访问局部变量所需的全部信息
例如,找出第一个大于等于给定长度的单词。
函数biggies实现
1 2 3 4 5 |
|
lambda捕获和返回
(1)值捕获
与传值参数类似,采用值捕获的前提是变量可以拷贝,与参数不同,被捕获的变量的值是在lambda创建时拷贝,而不是调用时拷贝
1 2 3 4 5 6 7 |
|
由于被捕获变量的值是在lambda创建时拷贝,因此随后对其修改不会影响到lambda内对应的值,上述中j的值为42
(2)引用捕获
1 2 3 4 5 6 7 |
|
(3)隐式捕获
可以让编译器根据lambda体中的代码推断我们要使用哪些变量,此时应在捕获列表中写一个&或=,&表示采用捕获引用,=表示采用值捕获方式。
1 |
|
(4)可变lambda
在值拷贝的情况下,lambda不会改变其值,若希望能够改变被捕获的变量的值,则在参数列表首加上mutable关键字。
1 2 3 4 5 6 7 |
|
一个引用捕获的变量能否可以修改依赖于此引用指向的是一个const还是非const类型
1 2 3 4 5 6 7 |
|
(5)指定lambda的返回类型
默认情况下,如果一个lambda体中包含return之外的任何语句,则编译器假定此lambda返回void。
例如:将一个序列中负数替换为其绝对值
1 |
|
transform接受三个参数,前两个表示迭代器输入序列,第三个表示迭代器目的位置。
上述中,我们无需指定返回类型,因此可以根据条件运算符的类型推断出来。
若改写成存在if语句,则存在错误
1 |
|
编译器发现存在return之外的语句,所以推断其返回类型为void,而他却返回了一个int
正确写法:
1 2 |
|
再探迭代器
标准库头文件iterator中还定义了额外几种迭代器,包括如下:
- 插入迭代器:绑定到一个容器上,向容器插入元素
- 流迭代器:绑定到输入输出流上,可以用来遍历所关联的IO流
- 反向迭代器:这些迭代器向后而不是向前移动,forwar_list不存在此迭代器
- 移动迭代器:移动元素专用
