泛型算法-1
泛型算法实现了一些经典算法的公共接口,如排序和搜索;称它们是“泛型的”,是因为它们可以用于不同类型的元素的和多种容器类型(不仅包括标准库类型,还包括内置的数组类型),以及其它类型的序列。
** 大多数算法都定义在头文件algorithm中 **
算法永远不会执行容器的操作
1 | /*算法find*/ |
向算法传递函数
算法谓词
- 算法谓词即标准库算法传递的参数, 可以指定算法的操作,它是一个可以调用的表达式,其返回结果是一个能用作条件的值
- 接受谓词参数的算法对输入序列中的元素调用谓词。因此元素类型必须能转换成谓词的参数类型
标准库算法所使用的谓词分为两类:
1.一元谓词:它们只接受一个参数
2.二元谓词:它们接受两个参数
1 | //定制操作,按照长度重新排vector |
这里向算法stable_sort传递的第三个参数就是一个谓词
lambda表达式(匿名函数)
lambda表达式与其它函数的区别是:lambda表达式可定义在函数内部
基本形式:
1 | [capture lsit](parameter list) -> return type {function body} |
- capture list(捕获列表): 一个lambda所在函数中的定义的局部变量的列表(通常为空)
- parameter list(参数列表)
- return type(返回类型)
- function body(函数体)
** 我们可以忽略形参列表和返回类型,但是必须永远包含捕获列表和函数体 **
1 | auto f = []{return 44;} ; |
上面的向算法stable_sort传递的实参可以改写为,效果还是一样的
1 | stable_sort(v.begin(), v.end(), [](const string &a,const string s&b){return a.size()<b.size()}); |
捕获列表的使用
一个lambda可以出现在一个函数内部,使用其局部变量,但它只能使用那些指明的变量。
1 |
|
** 捕获列表只用于局部非静态(static)变量,lambda可以直接使用局部static变量和在它所在函数之外声明的名字 **
lambada捕获和返回
- 变量的捕获方式有两种:值捕获、引用捕获
- 使用引用捕获变量时,必须确保被引用的对象在lambda执行的时候是存在的
- lambda捕获的是局部变量,这些变量在函数结束后就不复存在了
我们可以从一个函数返回lambda,函数可以直接返回一个可调用对象,或者返回一个类对象,该类含有可调用对象的数据成员。如果函数返回一个lambda,则与函数不能返回一个局部变量类似,此lambda也不能包含引用捕获
使用***&、=***进行隐式捕获
我们可以让编译器根据lambda体中的代码来推断我们要使用哪些变量
- **&**告诉编译器采用引用捕获方式
- **=**告诉编译器采用值捕获方式
混合使用显式捕获和隐式捕获时,显示捕获必须使用与隐式捕获不同的方式
1 |
|
指定lambda的返回类型
- 要为一个lambda定义返回类型时,必须使用尾置返回类型
- 尾置返回类型跟在形参列表后面,并以一个
->
符号开头
1 | auto f = [](int i)->int{ return i+1;}; |
可变lambada
使用关键字mutable
改变一个被捕获变量的值
1 | int i=1; |
lambda捕获列表
说明 | |
---|---|
[] | 空捕获列表。lambda不能使用所在函数中的变量。一个lambda只有捕获变量后才能使用它们 |
[names] | names是一个逗号分隔的名字列表,这些名字都是lambda所在函数的局部变量。默认情况下,捕获列表中的变量都被拷贝 |
[&] | 隐式捕获列表,采用隐式捕获方式 |
[=] | 隐式捕获列表,采用值捕获方式 |
[&, identifier_list] | identifier_list是一个逗号分隔的列表,包含0个或多个来自所在函数的变量,这些变量采用值捕获方式。任何隐式捕获的变量都采用引用方式捕获 |
[=, identifier_list] | identifier_list是一个逗号分隔的列表,包含0个或多个来自所在函数的变量,这些变量采用引用捕获方式,且变量名字前必须使用&。任何隐式捕获的变量都采用值方式捕获 |