【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

暂略

 

posted @ 2023-03-02 20:10  啊原来是这样呀  阅读(22)  评论(0)    收藏  举报