前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++11 lambda表达式小结

C++11 lambda表达式小结

作者头像
Enterprise_
发布2019-10-28 10:10:29
4170
发布2019-10-28 10:10:29
举报
文章被收录于专栏:小L的魔法馆

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:https://blog.csdn.net/Enterprise_/article/details/102770174

文章目录
  • 简介
  • 结构
    • return type
    • parameter list
    • capture list
  • 值捕获和引用捕获
  • 变量修改
  • 隐式和显式捕获
  • 捕获列表小结:
  • examples
  • problems
    • 1.为什么需要使用mutable才能进行修改?

简介

lambda表达式是一个匿名内联函数,可以定义别的函数体中,其形式如下:

代码语言:javascript
复制
[capture list](parameter list)->return type{funtion body}

从中可以看到,lambda只能使用尾置返回类型; 尾置返回类型放在参数列表后边以->开头,然后再原来放返回类型的地方放一个auto。

结构

lambda不可缺少的部分是捕获列表capture list和函数体funtion body,其他都可以忽略不写。

return type

return type会根据funtion body中的内容来推断,如果只含有一个return 语句,类型就从其推断,否则就是void。如果不是上述情况,就需要自己定义一个返回类型,防止推断为void和期望返回的类型不符合的问题。

parameter list

parameter list需要实参和形参互相匹配,且lambda不能有默认参数,所以两者属于也要相等。

capture list

capture list是lambda所在函数中定义的局部变量,lambda可以对其进行捕获然后进行使用,捕获过程也分为值和引用,使用时看是否需要对捕获的变量进行修改和所捕获的变量是否支持这种操作。

值捕获和引用捕获

值捕获需要变量能被拷贝,比如IO流是不能被拷贝,这就只能用引用。 有时可能需要返回一个lambda,当返回时,此lambda就不能用到引用,否则就会出现函数将返回一个局部变量的引用,这是不合法的。 引用捕获需要对象存在。

变量修改

lambda在捕获的时候就对变量进行了复制(值捕获时),所以希望能借此修改外部变量,应该时用引用。但是如果只需要就地对捕获的变量进行修改并且不想对外部修改的话,就可以在值捕获时在参数列表之后指明mutable关键字。

隐式和显式捕获

显示就是直接写出局部变量,隐式就是不在capture list中写出名字,只写捕获方式,其中 = (代表值捕获), & (代表引用捕获),让编译器自己推断要使用那些变量。 比如:

代码语言:javascript
复制
[ = ](string s1){return s1.size()>=length;}  //假设length为一个局部变量,则此时采用值捕获。

两者也可以混搭,这有一个要求:capture list中第一个元素必须为隐式捕获,并且显示和隐式捕获的方式必须不同。 比如:

代码语言:javascript
复制
[ = ,&os](string &s){ os << s << tmp; } //假设tmp为局部变量,采用了值捕获,则只能用显示捕获

捕获列表小结:

列表

含义

[]

空捕获列表

[n1,&n2,n3,&n4…]

以逗号为分隔的捕获列表,显示捕获

[&]

隐式捕获,lambda中使用的变量全部采用引用捕获

[=]

隐式捕获,lambda中使用的变量全部采用值捕获

[&,n1,n2]

混和捕获,n1和n2值捕获,其余为引用捕获

[=,&n1,&n2]

混和捕获,n1和n2引用捕获,其余为值捕获

examples

代码语言:javascript
复制
#include<bits/stdc++.h>
using namespace std;
void elimDups(vector<string>& words) {
	sort(words.begin(), words.end());
	auto end_unique = unique(words.begin(), words.end());
	//for (auto i : words)cout << i << " "; cout << endl;
	words.erase(end_unique, words.end());
	//for (auto i : words)cout << i << " "; cout << endl;
}

//countwords返回一个计数值,表示有多少个元素长度大于等于sz
int countwords(vector<string>& words, vector<string>::size_type sz) {
	elimDups(words);//字典序排序,删除重复元素;
	stable_sort(words.begin(), words.end(), [](const string& s1, const string& s2) {return s1.size() < s2.size(); });//长度排序,长度相同也维持字典序
	//for (auto i : words)cout << i << " "; cout << endl;
    auto it = count_if(words.begin(), words.end(), [sz](const string& s) { return s.size() >= sz; });
	return it;
}
int main(void) {
	vector<string>words;
	string str;
	while (cin >> str) {
		words.push_back(str);
	}
	//for (auto i : words)cout << i << " "; cout << endl;
	int cnt = countwords(words, 5);//计算有多少个元素长度大于等于5
	cout << cnt << endl;
	//the quick red fox jumps over the slow red turtle
	auto f=[&]()->bool  {
		while (cnt > 0)cnt--;
		if (cnt == 0)return true;
	};
	cout << f() << endl;//调用lambda改变变量
	cout << cnt << endl;
	cout << f() << endl;//再调用lambda不再改变变量
	cout << cnt << endl;
	return 0;
}
代码语言:javascript
复制
input:
the quick red fox jumps over the slow red turtle
output:
3
1
0
1
0

problems

1.为什么需要使用mutable才能进行修改?

lambda在定义时,编译器就会生成一个对应的匿名类,该类会包含所有被捕获的变量作为数据成员初始化,并且该类的operator()默认时const,这就导致无法修改类中的成员函数,加上mutable,即可转换为非const,就可以就地修改了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/10/27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 简介
  • 结构
    • return type
      • parameter list
        • capture list
          • 1.为什么需要使用mutable才能进行修改?
      • 值捕获和引用捕获
      • 变量修改
      • 隐式和显式捕获
      • 捕获列表小结:
      • examples
      • problems
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档