C++ 特性之 lambda
简而言之,Lambda 表达式就是用于创建匿名函数的。
或许,Lambda 表达式算得上是 C++ 11 新增特性中最激动人心的一个。这个全新的特性听起来很深奥,但却是很多其他语言早已提供(比如 C#)或者即将提供(比如 Java)的。
GCC 4.5.x 和 Microsoft Visual Studio 早已提供了对 lambda 表达式的支持。在 GCC 4.7 中,默认是不开启 C++ 11 特性的,需要添加 -std=c++11 编译参数。而 VS2010 则默认开启。
为什么说 lambda 表达式如此激动人心呢?举一个例子。标准 C++ 库中有一个常用算法的库,其中提供了很多算法函数,比如 sort() 和 find()。这些函数通常需要提供一个“谓词函数 predicate function”。所谓谓词函数,就是进行一个操作用的临时函数。比如 find() 需要一个谓词,用于查找元素满足的条件;能够满足谓词函数的元素才会被查找出来。这样的谓词函数,使用临时的匿名函数,既可以减少函数数量,又会让代码变得清晰易读。
语法:
C++ 11 的写法完全类似 JavaScript 的语法。
Lambdas are a great addition to C++. They offer a very practical way of defining short functions in your code.The full syntax goes like this:
[ capture-list ] ( params ) -> ret { body }
1)capture-list: This defines what variables will be visible inside the lambda scope. [ ]称为 lambda 引入符(lambda-introducer),lambda 引入符是有其自己的作用的,不仅仅是表明一个 lambda 表达式的开始那么简单。lambda 表达式可以使用与其相同范围scope内的变量。这个引入符的作用就是表明,其后的 lambda 表达式以何种方式使用(正式的术语是“捕获”)这些变量。
float f0 = 1.0;
std::cout << [=](float f) { return f0 + std::abs(f); } (-3.5);
其输出值是 4.5。[=] 意味着,lambda 表达式以传值的形式捕获同范围内的变量f0。另外一个例子:
float f0 = 1.0;
std::cout << [&](float f) { return f0 += std::abs(f); } (-3.5);
std::cout << '\n' << f0 << '\n';
输出值是 4.5 和 4.5。[&] 表明,lambda 表达式以传引用的方式捕获外部变量f0。
对于[]的形式,如果要使用 this 指针,必须显式传入:
[this]() { this->someFunc(); }();
总结下所有出现的 lambda 引入符:
[] // 不捕获任何外部变量
[=] // 以值的形式捕获所有外部变量
[&] // 以引用形式捕获所有外部变量
[x, &y] // x 以传值形式捕获,y 以引用形式捕获
[=, &z]// z 以引用形式捕获,其余变量以传值形式捕获
[&, x] // x 以值的形式捕获,其余变量以引用形式捕获
2)params: This is the function parameters type list that can be passed to the lambda scope. if no parameters, C++11 lets us skip the parentheses(圆括号) altogether.
3)ret: This is the return type of the lambda function. Just like params, this parameter can be omitted if the return type is void.
4)body: This is obviously your code body where you have access to your capture-list,and params, and which must return a variable with a type ret.
举个例子:
#include <algorithm>
#include <cmath>
void abssort(float *x, unsigned N)
{
std::sort(x,
x + N,
[](float a, float b) { return std::abs(a) < std::abs(b); });
}
C++的lambda表达式使用一对方括号作为开始的标识,类似于声明一个函数,只不过这个函数没有名字,也就是一个匿名函数。这个匿名函数接受两个参数,a和b;其返回值是一个 bool 类型的值,注意,返回值是自动推断的,不需要显式声明,不过这是有条件的!条件就是,lambda 表达式的语句只有一个 return。函数的作用是比较 a、b 的绝对值的大小。然后,在此例中,这个 lambda 表达式作为一个闭包被传递给 std::sort() 函数。
下面,我们来详细解释下这个神奇的语法到底代表着什么。
我们从另外一个例子开始:
std::cout << [](float f) { return std::abs(f); } (-3.5);
输出值是什么?3.5!注意,这是一个函数对象(由 lambda 表达式生成),其实参是 -3.5,返回值是参数的绝对值。lambda 表达式的返回值类型是语言自动推断的,因为std::abs()的返回值就是 float。注意,前面我们也提到了,只有当 lambda 表达式中的语句“足够简单”,才能自动推断返回值类型。
C++ 11 的这种语法,其实就是匿名函数声明之后马上调用(否则的话,如果这个匿名函数既不调用,又不作为闭包传递给其它函数,那么这个匿名函数就没有什么用处)。如果你觉得奇怪,那么来看看 JavaScript 的这种写法:
function() {} ();
function(a) {} (-3.5);
如果我不想让 lambda 表达式自动推断类型,或者是 lambda 表达式的内容很复杂,不能自动推断怎么办?比如,std::abs(float)的返回值是 float,我想把它强制转型为 int。那么,此时,我们就必须显式指定 lambda 表达式返回值的类型:
std::cout << [](float f) -> int { return std::abs(f); } (-3.5);
这个语句与前面的不同之处在于,lambda 表达式的返回时不是 float 而是 int。也就是说,上面语句的输出值是 3。
Ref:
https://www.cnblogs.com/langzou/p/5962033.html
C++ 特性之 lambda的更多相关文章
- Java笔记——Java8特性之Lambda、方法引用和Streams
Java8已经推出了好一段时间了,而掌握Java8的新特性也是必要的,如果要进行Spring开发,那么可以发现Spring的官网已经全部使用Java8来编写示例代码了,所以,不学就看不懂. 这里涉及三 ...
- Java8特性之Lambda、方法引用和Streams
这里涉及三个重要特性: Lambda 方法引用 Streams ① Lambda 最早了解Lambda是在C#中,而从Java8开始,Lambda也成为了新的特性,而这个新的特性的目的,就是为了消除单 ...
- java8新特性: lambda表达式:直接获得某个list/array/对象里面的字段集合
java8新特性: lambda表达式:直接获得某个list/array/对象里面的字段集合 比如,我有一张表: entity Category.java service CategoryServic ...
- Java8特性之Lambda、方法引用以及Stream流
Java 8 中的 Streams API 详解:https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/ Java笔记——Jav ...
- JDK8新特性之一Lambda
JDK8的新特性之一Lambda能将函数作为方法里面的参数使用. /** * JDK8新特性Lambda */ public class Test { public static void main( ...
- Java8 新特性学习 Lambda表达式 和 Stream 用法案例
Java8 新特性学习 Lambda表达式 和 Stream 用法案例 学习参考文章: https://www.cnblogs.com/coprince/p/8692972.html 1.使用lamb ...
- Java8新特性系列-Lambda
转载自:Java8新特性系列-Lambda – 微爱博客 Lambda Expressions in Java 8 Lambda 表达式是 Java 8 最流行的特性.它们将函数式编程概念引入 Jav ...
- Java 高级特性: Lambda 表达式
本文源代码上传到了码云,请点击 LambdaExpression 获取.Lambda 表达式是 java 8 的新特性,本文讲解了 lambda 表达式的所有知识.内容涉及到 lambda 表达式是什 ...
- jdk1.8新特性之lambda表达式及在Android Studio中的使用举例
Jdk1.8已经出很久了但是很多同学对它的特性在android studio 中的应用可能还不是很熟悉,今天我们就来对这个新特性在AS中做它的应用实践. 一.首先在有JDK1.8的情况下我们要在AS的 ...
- Python高级特性: 函数编程 lambda, filter,map,reduce
一.概述 Python是一门多范式的编程语言,它同时支持过程式.面向对象和函数式的编程范式.因此,在Python中提供了很多符合 函数式编程 风格的特性和工具. 以下是对 Python中的函数式编程 ...
随机推荐
- goland 安装破解
链接:https://pan.baidu.com/s/1vH70CHq122RbfwLwbHewjg 密码:zilv 复制如下注册码: 56ZS5PQ1RF-eyJsaWNlbnNlSWQiOiI1 ...
- 开源GIT仓库-----gitlab
简介:GitLab是一个利用 Ruby on Rails 开发的开源应用程序,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目.它拥有与Github类似的功能,能够浏览源代码 ...
- 用java将简单的word文档换成pdf文档
用java将简单的word文档换成pdf文档的方式很多,因为很多都没有实际测试过,所以这里就先泛泛的说一下 整体上来看分两种: 1.纯java代码实现,有很多优秀的开源软件可以用,比如poi,itex ...
- Java垃圾回收(java GC)
一.GC的阶段 对每个对象而言,垃圾回收分为两个阶段:finalization和reclamation. finalization: 指运行这个对象的finalize的方法. reclamation: ...
- Java 从入门到进阶之路(十六)
在之前的文章我们介绍了一下 Java 中类的多态,本章我们来看一下 Java 中类的内部类. 在 Java 中,内部类分为成员内部类和匿名内部类. 我们先来看一下成员内部类: 1.类中套类,外面的叫外 ...
- gitlab搭建与基本使用【转】
一.git.github.gitlab的区别Git是版本控制系统,Github是在线的基于Git的代码托管服务.GitHub是2008年由Ruby on Rails编写而成.GitHub同时提供付费账 ...
- oracle/mysql经典电子书籍pdf下载
Oracle LZ写的书,深入结合oracle设计.优化/SQL优化.应用层架构与优化.大量生产案例,敬请期待... Oracle编程艺术 深入理解数据库体系结构(第3版) 链接:https://pa ...
- java的集合类【Map(映射)、List(列表)与Set(集)比较】
https://baike.baidu.com/item/java%E9%9B%86%E5%90%88%E7%B1%BB/4758922?fr=aladdin https://www.cnblogs. ...
- linux: 右键添加打开终端
安装一个包,即可在右键里面添加一个“打开终端”的菜单. sudo apt-get install nautilus-open-terminal 注销用户重启,然后再进入就可以右键->在终端打开选 ...
- Visual Studio 2019更新到16.2.3
Visual Studio 2019更新到16.2.3 此次更新,包括以下内容: (1)修复找不到Android SDK的bug. (2)修复安装结束后,无法启动的bug. (3)修复关闭VS时, ...