Lambda 表达式和函数指针

image

Lambda 表达式和函数指针

1. 什么是Lambda表达式?

C++11引入了Lambda表达式,它是一种用于创建匿名函数的方法。Lambda表达式在编写更简洁、清晰的代码时非常有用,特别是在需要传递函数作为参数的情况下,比如STL算法、自定义排序函数、回调等。

Lambda表达式的形式

Lambda表达式的一般形式如下:

[捕获列表](参数列表) mutable-> 返回类型 {
   
    // 函数体
}

让我们详细讲解Lambda表达式的各个部分以及如何使用它们:

  1. 捕获列表(Capture List) :Lambda表达式可以在其内部访问外部作用域的变量。捕获列表用于指定Lambda表达式需要捕获哪些外部变量以供使用。(不能省略)
    捕获列表有三种形式:
    • []:不捕获任何变量。
    • [变量名]:捕获指定变量(复制捕获)。
  • [&变量名]:引用捕获,以引用方式访问变量(引用捕获)。
    • [=]:以复制捕获方式捕获所有外部变量。
    • [&]:以引用捕获方式捕获所有外部变量。
  1. 参数列表(Parameter List) :与普通函数类似,如果不需要参数传递,则可以连同()一起省略,用于指定Lambda表达式的参数列表。
  2. 返回类型(Return Type) :可以省略,编译器可以自动推断返回类型。如果存在返回语句,编译器会根据返回语句推断返回类型。如果Lambda表达式中包含多条语句,且需要指定返回类型,可以使用->符号。
  3. mutable : 默认情况下,lambda总是一个const函数,mutable可以取消其常量性,使用该修饰符时,参数列表不可省略(即使参数为空)。mutable放在参数列表和返回值之间。
  4. 函数体(Function Body) :Lambda表达式的具体实现,包含要执行的代码(不能省略)。

在lambda函数定义中,参数列表和返回值都是可选部分,而捕获列表和函数体可以为空。C++11中最简单的lambda函数为:[]{}; 该lambda函数不能做任何事情,没有意义。

Lambda表达式的隐式捕获

除了显式列出我们希望使用的来自所在函数的变量之外,还可以让编译器根据lambda体中的代码来推断我们要使用哪些变量。为了指示编译器推断捕获列表,应在捕获列表中写一个&或=。&告诉编译器采用捕获引用方式,=则表示采用值捕获方式。例如:

//sz为隐式捕获,值捕获方式
auto wc = find_if(words.begin(),words.end(),[=](const string &s)
				  {
   return s.size() >= sz;});

隐式捕获和显示捕获也可以混合使用,如下代码:

void elimDups(vector<string>& words)
{
   
	//对words按照字典序进行升序排序
	sort(words.begin(),words.end());
	//将重复的字符移动至words后半部分,并返回前半部分最后一位的下一位的迭代器
	auto end_unique=unique(words.begin(),words.end());	
	//删除后部分的内容
	words.erase(end_unique,words.end());
}

void biggies(vector<string> &words,vector<string>::size_type sz,ostream &os,char c = ' ')
{
   
	//按照字典序排序,去重
	elimDups(words);
	//按照字符串长度升序排序,当长度相同时,维持字典序
	stable_sort(words.begin(),words.end(),
	[](const string& a,const string& b)->bool
	{
   return a.size() < b.size();});

	//返回第一个长度大于等于sz的迭代器
	auto wc=find_if(words.begin(),words.end(),[sz](const string& s)->bool
	{
   return s.size()>=sz;});

	//os 隐式捕获,引用捕获,c显示捕获,值捕获
	for_each(words.begin(),words.end(),[&,c](const string &s){
   os<<s<<c;});
	//os显示捕获,引用捕获,c隐式捕获,值捕获
	for_each(words.begin(),words.end(),[=,&os](const string &s){
   os<<s<<c;});
}

当我们混合使用隐式捕获和显式捕获时,捕获列表中的第一个元素必须是一个&或=。此符号指定了默认捕获方式为引用或值。且当混合使用隐式捕获和显式捕获时,显式捕获的变量必须使用与隐式捕获不同的方式。

image.png

可变Lambda

默认情况下,对于一个值被拷贝的变量,lambda不会改变其值。如果我们希望能改变一个被捕获的变量的值,就必须在参数列表首加上关键字mutable。

void fcn3()
{
   
	size_t v1=42;
	//通过mutable,f可以改变它所捕获的值
	auto f = [v1]() mutable{
   return ++v1;};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值