C++ lambda表达式

lambda表达式

lambda表达式形式

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

capture list 捕获列表是一个lambda所在函数中定义的局部变量的列表。return type、 parametes list 和function body和普通函数一样是返回类型,参数列表,函数体。

我们可以忽略参数列表和返回类型,但是一定要有函数体和捕获列表。

auto f = []{return 42;};
cout << f() << endl;

捕获方式

值捕获

类似于参数传递,变量的捕获方式也可以是拷贝或者引用。

void func1(){
	size_t v1 = 42; //局部变量
	auto f = [v1]{return v1};
	v1 = 0;
	auto j = f(); //j等于42
} 

引用传递
void func2(){
	size_t v1 = 42; //局部变量
	auto f2 = [&v1]{return v1};
	v1 = 0;
	auto j = f2(); //j等于0;f2保存v1的引用。
} 

引用捕获和返回引用有着相同的问题,因为lambda捕获的是局部变量,这些变量在函数结束后就不存在了。如果lambda在函数结束后执行,捕获引用的对象已经消失了。

但是引用捕获是必要的,但某个对象无法拷贝时,如os对象(输入输出对象)

隐式捕获

可以让编译器更具lambda体的代码来推断我们需要哪些变量。为了指示编译器推断捕获列表,应在捕获列表中写一个&或=

  • & 表示编译器使用的是引用捕获
  • = 表示编译器使用的是值捕获
wc = find_if(words.begin(), words.end(),
	[=](const string &s)
		{return s.size() >= sz;}

该lambda表达式会直接捕获lambda所在函数体里面叫sz的局部变量,并且使用引用捕获。

如果打算一些变量使用值捕获,一些使用引用捕获,那么就需要隐式和显式同时使用。

可变lambda

对于一个被捕获的变量,希望能更改它的值,就必须加入mutable

void func3(){
	size_t v1 = 42;
	auto f = [v1]()mutable{return v1++};
	v1 = 0;
	auto j = f(); //j = 43;
}

对于引用捕获的变量也是如此

void func4(){
	size_t v1 = 42;
	auto f = [&v1]()mutable{return v1++};
	v1 = 0;
	auto j = f(); //j = 1;
}

指定返回类型

默认情况下,若一个lambda体包含return之外的任何语句,编译器假定该lambda返回void。

现在使用一个标准库的transfrom算法和一个lambda来将一个序列中的每个负数替换成了绝对值。

transfrom(vi.begin(), vi.end(), vi.begin(),[](int i){return i < 0?-i:i});

函数transfrom接受三个迭代器,前两个迭代器表示输入序列,第三个迭代器表示目的地位置。算法对序列的每个元素调用可调用对象。并将结果写道目的地位置。

在上面这个例子,该lambda体是单一的return语句,返回一个条件表达式的结果。无需指定返回类型,便可推断出来。

transfrom(vi.begin(), vi.end(), vi.begin(),[](int i){if(i<0) return -i;else return i});

这个lambda表达式返回的是void类型,但是我们需要返回int类型。

这样的话,就必须使用尾置返回类型

transfrom(vi.begin(), vi.end(), vi.begin(), 
	[](int i)-> int	{if(i<0) return -i;else return i});

lambda优于普通函数的地方

按道理,lambda表达式大都可以被函数替代,那在哪些场景下,必须要用lambda表达式不可。

先讲一下find_if函数
在这里插入图片描述

find_fi()函数需要传入一对迭代器,指向的是输入序列。第三个参数是一个要返回bool的函数。

当函数不返回false,即它第一次返回true时,find_if返回该迭代器。

现在想要知道第一个word长度大于3的word

int size = 3;
auto iter = find_if(words.begin(), words.end(), 
	[size](const string word){ return word.size() > size});

从截图可以看出,该函数只能接受一个参数。

如果要用函数替代lambda ,用下面这个函数是不ok的。

而lambda可以通过捕获size,不使用两个参数,从而解决了这个问题。

bool check_size(const string word, string::size size){
	if(word.size() > size){
		return true;
	}else{
		return false;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++ Lambda表达式是一种简洁的匿名表示方法,可以在代码中定义并使用。Lambda表达式的格式一般为:[] (参数列表) mutable -> 返回值类型 { 表达式 }。Lambda表达式可以捕获外部变量,并将其作为参数传递给函数体部分进行处理。Lambda表达式在使用时可以作为函数对象、函数指针或者函数参数进行传递。 Lambda表达式的底层原理是通过生成一个匿名类来实现。该类会重载函数调用运算符(),并包含Lambda表达式的函数体。Lambda表达式中捕获的外部变量会以成员变量的形式存储在该类中。当Lambda表达式被调用时,实际上是调用了该类的重载函数调用运算符()。 Lambda表达式可以与std::function结合使用,以实现函数对象的灵活使用。也可以将Lambda表达式赋值给相同类型的函数指针,实现函数指针的使用。但一般不建议这样使用,因为Lambda表达式已经提供了更加方便和简洁的方式。 总结来说,C++ Lambda表达式是一种用于定义匿名函数的语法,可以捕获外部变量并进行处理。其底层通过生成一个匿名类来实现,并提供了与std::function和函数指针的结合使用方式。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [C++11:lambda表达式](https://blog.csdn.net/zhang_si_hang/article/details/127117260)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值