【C++】13.泛型算法与Lambda表达式[深蓝学院C++第11章]
一.泛型算法
1.1定义
泛型算法:可以支持多种类型的算法
1.2需求来源
讨论对象:C++标准库中定义的算法,涉及到的头文件<algorithm><numeric><ranges>
为什么引入泛型而不采用方法:
(1)内建数据类型不支持方法,如数组并没有什么方法
(2)计算逻辑存在相似性,避免重复定义
泛型算法通常都不复杂,但优化足够好
一些泛型算法与方法同名、功能类似,此时建议使用方法而非算法:std::find VS std::map::find,优先用专用的再次通用的
1.3实现方式
如何实现支持多种类型:通常使用迭代器作为算法与数据的桥梁
1.4分类
(1)读算法,给定迭代区间,读取其中的元素并进行计算,accumulate/find/count
(2)写算法,向一个迭代区间中写入元素,如单纯的写fill、fill_n,读写操作transpose(转换并写入)、copy,注意写算法一定要保证目标区间足够大
(3)排序算法,改变输入序列中元素的顺序,sort、unique(去重)
1.5迭代器
泛型算法使用迭代器实现元素访问
基于容器的、常见的迭代器分类:
(1)输入迭代器:可读,可递增——典型应用为find算法
(2)输出迭代器:可写,可递增——典型应用为copy算法
(3)前向迭代器:可读写,可递增——典型应用为replace算法
(4)双向迭代器:可读写,可递增递减——典型应用为reverse算法
(5)随机访问迭代器:可读写,可增加一个整数——典型应用为sort算法
一些算法会根据迭代器类别的不同引入相应的优化:如计算两个元素间距离的distance算法
特殊的迭代器:(略)
(1)插入迭代器,
(2)流迭代器,
(3)反向迭代器,
(4)移动迭代器,
1.6迭代器与哨兵
哨兵:Sentinel,用于标识访问区间的结尾
1.7并发算法(略)
std::execution::seq
std::execution::par
std::execution::par_unseq
std::execution::unseq
二.bind与lambda表达式
很多算法允许通过“可调用对象”自定义的计算逻辑
如何定义“可调用对象”:
(1)函数指针,概念直观,但定义位置受限
(2)类,功能强大,但书写麻烦
(3)bind:基于已有的逻辑灵活适配,但描述复杂逻辑时语法可能会比较复杂难懂
(4)lambda表达式,小巧灵活,功能强大
2.1bind
bind,修改可调用对象的调用方式
std::copy_if(x.begin(),x.end(),std::back_inserter(y),std::bind2st(std::greater<int>(),3));
历史:C++11引入,早起的bind:std::bind1st,std::bind2nd,具有bind的基本思想但功能有限
特性:
(1)调用std::bind时,传入的参数会被复制,这可能会产生一些调用风险
(2)可以使用std::ref或std::cref避免复制的行为
使用方式
1 bool myPredict(int val1,int val2){ 2 return val1 > val2; 3 } 4 int main(){ 5 using namespace std::placeholders; 6 7 auto x = std::bind(myPredict,_1,3); 8 std::cout << x(50); 9 }
其中:占位符表示输入的第几个参数放在哪个位置
2.2lambda表达式
需求:为了更灵活地实现可调用对象而引入,
1 auto x =[](int val){return val > 3;}; 2 std::cout << x(5) << std::endl;
从C++11开始引入,
Lambda表达式会被编译器翻译成类进行处理,
lambda表达式的基本组成部分:
(1)参数与函数体,包括[]、形参列表、普通函数体+;
(2)返回类型,编译器自动推导,前提是所有return语句的表达式类型是相同的;如果不同,可以在函数签名后用 -> type的方式来指定;
(3)捕获,针对函数体中使用的局部自动对象进行捕获,包括值、引用和混合捕获,this捕获,初始化捕获,*this捕获
传入y,auto x =[y](int val){return val > 3;};y被复制进临时类中
传入&y,auto x =[&y](int val){return val > 3;};y的引用被传进临时类中,不需要加mutable
(4)说明符,mutable/constexpr/consteval,暂略
(5)模板形参
Lambda的深入应用:略
(1)即调用函数表达式
(2)捕获时计算
(3)使用auto避免复制
(4)Lifting
(5)递归调用
三.泛型算法的改进——ranges
暂略

浙公网安备 33010602011771号