风骚的lambda
来源:互联网 发布:ps cs6 mac破解版 编辑:程序博客网 时间:2024/05/16 12:52
- lambda
- 向lambda传递参数
- 使用捕获列表
- lambda捕获和返回
- 值捕获
- 引用捕获
- 隐式捕获
- 可变lambda
- 尾置返回
在c++11中,增加了不少的特性,才发现先的c++是如此的风骚
lambda
一个lambda表达式表示一个可调用的代码单元。我们可以将其理解为一个未命名的内联函数。与任何函数类似,一个lambda具有一个返回类型、一个参数列表、和一个函数体,但与函数不同,lambda可能定义在函数内部。一个lambda表达式具有如下形式
[capture list](parameter list)-> return type{function body}
- capture list(捕获列表)是一个lambda**所在函数定义局部变量**的列表(通常为空)
- return type:返回类型
- parameter list:参数列表
- function body:函数体
后面三个和普通函数一样,但是lambda必须使用尾置返回来指定类型,尾置返回简单说明在文章后面
* 我们可以忽略参数列表和返回类型,但必须永远包含捕获列表和函数体
* 在lambda中忽略括号和参数列表等价于指定一个空参数列表。
* 如果忽略返回类型,lambda根据函数体中的代码推断出返回类型,如只有一个return语句,则从返回表达式类型推断出来
* 如果lambda的函数体包含任何单一return语句之外的内容,且未指定返回类型,则返回void
忽略参数列表和返回类型的example
auto f = [] {return 42;};cout << f() << endl;//打印42// 注意是f()而不是f
向lambda传递参数
[](const string &a,const string &b) {return a.size()<b.size();}//使用//按长度排序,长度相同的单词维持字典序stable_sort(words.begin(),words.end(), [](const string &a,const string &b) {return a.size()<b,size();} );
空捕获列表表面此lambda不使用它所在函数中的任何局部变量。
使用捕获列表
一个lambda通过将局部遍历包含在其捕获列表中来指出将会使用这些变量,在这个例子中,lambda会捕获sz,并只有单一的string参数
[sz]{const string &a} {return a.size()>=sz};
- 捕获列表只用于局部非static变量,lambda可以直接使用局部static变量和他所在函数之外声明的名字
完整的biggies
void biggies(vector<sting &words>,vector<string>::sizetype sz){ elimDups(words); //将word按字典序排毒,删除重复单词 //按长度排序,长度相同单词维持字典序 stable_sort(words.begin(),words.end(), [](const string &a,const string &b) {return a.size()<b,size();} ); //获取一个迭代器指向第一个满足size()>sz的元素 auto wc = find_if(words.begin(),words.end(), [sz](const string &a) { return a,size()>=size; }); //计算满足size>=sz的元素的数目 auto count = words.end()-wc; cout<<count<<" "<<make_pliral(count,"word",'s')<<" of length "<<sz<<" or longer"<<endl; //打印长度大于等于给定值的单词,每个单词后面接一个空格 for_each(wc,words.end(), [](const string &s){cout<<s<<" ";}); cout<<endl;}
lambda捕获和返回
每个lambda表达式的类型是独一无二的。当向一个函数传递一个lambda时,同时定义了一个新类型和该类型的一个对象。
默认情况下,从lambda生成的类都包含一个对应 该lambda所捕获的变量的数据成员。
可以使用decltype关键字声明一个该类型成员
值捕获
被捕获的值是在lambda创建时拷贝,而不是调用时拷贝:
void fcn1(){ size_t v1=42; //局部变量 //将v1拷贝到名为f的可调用对象 auto f = [v1]{return v1}; v1=0; auto j = f(); //j为42,f保存了我们创建它时v1的拷贝}
引用捕获
void fcn2(){ size_t v1=42; //局部变量 //对象f2包含v1引用 auto f2 = [&v1]{return v1}; v1=0; auto j = f2(); //j为0,f保存了v1的引用}
如果必须采用引用方式捕获一个变量,必须保证被引用的对象在lambda执行的时候是存在的
隐式捕获
除了显示列出我们希望使用的来自所在函数的变量之外,还可以指示编译器根据lambda体中的代码来推断我们需要使用那些变量。
为了指示编译器推断捕获列表,应在捕获列表中写一个&或=。&告诉编译器采用捕获引用方式,=表示采用值捕获方式。
例如重写的find_if
//sz为隐式捕获,值捕获方式wc = find_if(words.begin(),words.end, [=](const string &s){return s.size()>=sz; });
如果希望对一部分变量采用值捕获,对其他变量采用引用捕获,可以混合使用隐式捕获和显示捕获,但捕获列表中的第一个元素必须是一个&或=
可变lambda
如果我们希望能改变一个被捕获的变量的值,就必须在参数列表首加上关键字mutable
void fcn3(){ size_t v1 = 42; //f可以改变它所捕获的变量的值 auto f=[v1]() mutable { return ++v1; }; v1=0; auto j=f(); // j为43}
尾置返回
一般来讲,尾置返回类型是为了使用decltype,或者纯粹让代码变得更可读。
decltype的例子如下,譬如说你可能不知道a+b到底返回什么类型:
template<typename T, typename U>auto Add(T t, U u) -> decltype(t + u){ return t + u;}
这样你不仅可以Add(1, 2),还可以Add(3.0, 4.0f),甚至还可以Add(“VczhIsAGenius”, 7)了。
上述例子来自: https://segmentfault.com/q/1010000003763661
- 风骚的lambda
- 风骚的strlen
- 风骚的Guard语法
- 风骚的Toast
- NavigationView如此风骚的控件
- 这些话真的很风骚....
- 程序员也有风骚的青春
- 风骚裙摆--最后的内存池
- iPhoneX的faceID到底是一种怎样风骚的操作?
- iPhoneX的faceID到底是一种怎样风骚的操作?
- iPhoneX的faceID到底是一种怎样风骚的操作?
- 一个很风骚的二值互相交换语句
- 2015年将引领风骚的Web设计趋势
- 算法复习——风骚的快速排序
- Swoole Framework 入门教程(3)-风骚的入口文件
- 2、Power View—风骚的数据自动筛选
- 2015年将引领风骚的Web设计趋势
- 风骚一把
- win10安装教程
- scikit-learn的基本用法(一)——KNN算法的使用
- 关于Mysql线程的基本设置
- Django模糊查询
- 【上机笔试之十二】数位拆解-进制转换
- 风骚的lambda
- HTML5复习 (11)
- Android动画学习篇(一)【TweenAnimation】
- IntelliJ IDEA
- 山东第二届acm省赛总结:
- I
- 桶式排序
- chrome浏览器解决跨域问题
- ubuntu anaconda install opencv