【C++】超详细入门——lambda表达式

⚓️作者简介:即将大四的北京某能源高校学生。

📚座右铭:“九层之台,起于垒土” 。所以学习技术须脚踏实地。

📖这里推荐一款刷题、模拟面试神器,可助你斩获大厂offer:[点我免费刷题、模拟面试]


1、可调用对象

如果一个对象或表达式可以使用调用运算符(()),则可以称它为可调用对象。

可调用对象共有四种:

  • 函数
  • 函数指针
  • 重载了函数调用运算符的类
  • lambda表达式

可调用对象用途很广,包括在调用泛型算法函数(sort(),find_if()等)时,可以传入可调用对象,来指明泛型算法要对指定范围内的元素进行哪种操作。


2、谓词

再来看一下谓词的概念。

谓词是一个可调用的表达式,其返回结果是一个能用作条件的值。标准库算法所使用的的谓词分两类:

  • 一元谓词:只接受单一参数。
  • 二元谓词:接受两个参数。

一般来说,可调用对象在泛型算法中都被用作谓词传入函数。可以说谓词是可调用对象的一种,也可以说可调用对象可以当做谓词。


3、尾置返回类型

介绍lambda表达式之前,最后再引入一个概念:尾置返回类型。

C++11 中尾置返回类型用来简化函数声明,以一个跟在形参列表后面的 -> 开头,函数名前需要用 auto 来表明该函数的返回类型是用尾置返回类型表示的。

尾置返回类型尤其对于返回类型比较复杂的函数最有效,比如数组的指针或数组的引用:

//返回整型数组指针的函数,形参为一个int。
int (*func(int i))[10];
//使用类型别名
auto func(int i) -> int (*)[10];

这样看来使用类型别名声明复杂函数就更简洁明了吧。


4、lambda表达式

终于到它了——lambda表达式。

lambda表达式又称匿名函数,可以把他理解为未命名的内联函数。它必须使用尾置返回类型来定义,其定义形式为:

[capture list] (parameter list) -> return type {function body}

各部分解释:
capture list:是 lambda 所在函数中定义的局部变量的列表(一般不用);
return type:返回类型;
parameter list:参数列表;
function body:函数体。

4.1无参lambda表达式

lambda表达式中可以忽略参数列表和返回类型,忽略参数列表相当于空参数列表,忽略返回类型可以从 return 语句中推断出返回类型:

例子:

auto f = [] {return 0;};
auto f = [] () -> int {return 0;};  //等价定义
cout << f() << endl;

这里定义了一个可调用对象 f,不接受参数,返回 0。

4.2有参lambda表达式

与普通函数一样 lambda 的形参使用实参初始化。实参和形参的类型必须匹配,而且不能有默认参数。

例一:

bool is_shorter(const string &s1, const string &s2){
    return s1.size()<s2.size();
}
sort(words.begin(), words.end(), is_shorter);
sort(words.begin(), words.end(), [](const string &a, const string &b)
	{return a.size() < b.size();});//等价定义

接受二元谓词的 sort 用传入的谓词替代 < 操作。

第一个 sort 中把 is_shorter 函数作为二元谓词传入,将 vector<string> 按照字符串长度排序。
第二个把 lambda 表达式作为二元谓词传入,与上一个等价。

例二:

bool is_large(const string &s, string::size_type sz){
    return s.size() > sz;
}
auto iter = find_if(words.begin(), words.end(), is_large);
auto iter = find_if(words.begin(), words.end(), 
	[](const string &s, string::size_type sz){return s.size() > sz;})

这段代码看似是返回 vector<string> 中指向第一个长度大于 sz 的元素的迭代器,但是编译起来却会报错,这是因为 find_if 接受的参数是一元谓词,这里的 is_large 却是二元谓词。

别着急,利用capture list可以解决传入多个参数的问题。

4.3使用capture list

当 lambda 表达式出现在函数中,就可以使用函数中的局部变量,我们需要通过 capture list 指出将会使用的变量。

这样我们就可以直接使用局部变量 sz,而不用通过传参使用它了:

string::size_type sz = 5;
auto iter = find_if(words.begin(), words.end(), 
	[sz](const string &s){return s.size() > sz;})

🎉到此 lambda 表达式的讲解就结束了,从今天开始更新 C++ 的基础知识,后面应该会讲解一下标准容器,并手动实现。
希望大家多多关注,三连支持。你们的支持是我源源不断创作的动力。

评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的博仔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值