目录

目录 1

1. 什么是Lambda? 1

2. 语法格式 1

2.1. 语法格式 1

2.2. 最简定义 2

3. 应用示例 2

4. capture列表 3

4.1. 基本形式 3

4.2. 注意事项 3

5. 对比仿函数 3

6. 对比函数指针 4

7. Lamdba和STL 4

8. 参考资料 5

1. 什么是Lambda?

Lambda['læmdə]表达式是一个没有函数名的匿名函数,基于数学中的希腊字母λ演算得名。

2. 语法格式

2.1. 语法格式

Lambda函数的语法定义为:[capture] (parameters) mutable ->return_type { statement }。

1) capture

捕获列表,可以为空,但[]是必须的不能省略,编译器需要根据它来判断是否为Lambda函数。这个是整个Lambda中相对新鲜和复杂的地方,后面专节介绍。

区别于普通函数,捕获列表的意义在于:Lambda可直接访问父作用域中捕获列表所指定的变量,普通函数或类成员函数除了参数和类成员外,是不能访问父作用域(如调用它的父函数)中其它变量的。。

2) parameters

参数列表,和普通的函数没什么两样,如果没有参数,写可以写成(),不同于[],空的()也可省略。

3) mutable

修饰符,默认Lambda函数为const函数。

4) ->return_type

函数返回类型,在无返回值,或返回值可以推导出的情况下,可以省略。

5) statement

函数体,和普通函数体没有什么不同,但是除了可以使用参数外,还可以使用capture中所指定的变量。

2.2. 最简定义

通过以上规则,显然可以发现最简的Lambda函数定义:[] {};,这是一个什么也不做的空Lambda函数。

3. 应用示例

// 编译:g++ -std=c++11 -g -o x x.cpp

// 示例在g++ 4.8.2上编译通过

#include <stdio.h>

int main()

{

int boys = 4;  // 男生人数

int girls = 3; // 女生人数

// 计算男生和女生总人数,

// 这里必须用上C++11新定义的auto,

// total_child类似于指向函数的指针了,并带两个int类型的参数

auto total_child = [](int x, int y) -> int

{

return x + y;

};

// 调用

int x = total_child(girls, boys);

printf("%d\n", x);

return 0;

}

4. capture列表

4.1. 基本形式

这个是C++11 Lambda中非常有趣的地方,使用[]标识,有如下几种形式:

1) [var] 表示以值传递方式捕获变量var

2) [=] 表示以值传递方式捕获父作用域的所有变量,包括this

3) [&var] 表示以引用传递方式捕获变量var

4) [&] 表示以引用传递方式捕获父作用域的所有变量,包括this

5) [this] 表示以值传递方式捕获this

除以上5种基本形式化,还支持组合,如:

1) [=, &a, &b] 表示以引用传递方式捕获变量a和变量b,以值传递方式捕获父作用域的其它所有变量

2) [&, a, this] 表示以值传递方式捕获父作用域的变量a和this,以引用传递方式捕获其它所有变量

4.2. 注意事项

在上一节,可以看到捕获的几种基本形式,可以组合同时使用,但这里有个约束:不允许重复传递,比如:

1) [=, a] 由于=表示以值传递方式捕获所有父作用域的变量,a就和它重复了,所以产生了语法错误

2) [&, &this] 同理,&this也重复了,同样是语法错误。

5. 对比仿函数

在C++中,仿函数就是用一个类来模仿含糊,虽然用得不多,但有时却需要它,比如自定义map的比较函数等场合。下面是一个仿函数示例:

// 编译:g++ -std=c++11 -g -o y y.cpp

// 示例在g++ 4.8.2上编译通过

#include <stdio.h>

// 定义一个仿函数

class functor

{

public:

// 仿函数的特点就是重载了类的()操作符

int operator ()(int x, int y) const

{

return x + y;

}

};

int main()

{

int boys = 4;

int girls = 3;

// 使用仿函数

functor total_child;

int x = total_child(girls, boys);

printf("%d\n", x);

return 0;

}

由于仿函数是借助class或struct来实现的,因此它可以有类成员,仿函数被广泛的应用在STL的实现当中,它和Lambda函数相似,但要复杂一点。

6. 对比函数指针

Lambda函数并非函数指针,在C++11标准中将它定义为闭包(Closure)的类,每个Lambda会产生一个闭包类型的临时对象(右值)。

虽然如此,但C++11标准允许Lambda表达式向函数指针的转换,前提是Lambda函数没有捕获任何变量,而且函数指针的原型必须和Lambda函数有相同的调用方式。

7. Lamdba和STL

Lamdba函数和STL中的for_each结合,是最典型的应用场景,它相比其它方式都显得更为简约:

// 编译:g++ -std=c++11 -g -o z z.cpp

// 示例在g++ 4.8.2上编译通过

#include <algorithm>

#include <stdio.h>

#include <vector>

using namespace std;

void print(int i)

{

printf("%d\n", i);

}

int main()

{

vector<int> nums;

nums.push_back(2);

nums.push_back(0);

nums.push_back(1);

nums.push_back(4);

// 传统的for循环

for (auto iter=nums.begin(); iter!=nums.end(); ++iter)

{

printf("%d\n", *iter);

}

// 使用函数指针

for_each(nums.begin(), nums.end(), print);

// 使用Lamdba函数

for_each(nums.begin(), nums.end(), [=](int i)

{

printf("%d\n", i);

});

return 0;

}

8. 参考资料

推荐进一步阅读:《深入理解C++11:C++11新特性解析与应用》。

C++11之Lambda特性探析的更多相关文章

  1. 【C++11】新特性——Lambda函数

    本篇文章由:http://www.sollyu.com/c11-new-lambda-function/ 文章列表 本文章为系列文章 [C++11]新特性--auto的使用 http://www.so ...

  2. 浏览器环境下JavaScript脚本加载与执行探析之defer与async特性

    defer和async特性相信是很多JavaScript开发者"熟悉而又不熟悉"的两个特性,从字面上来看,二者的功能很好理解,分别是"延迟脚本"和"异 ...

  3. 开源中文分词工具探析(三):Ansj

    Ansj是由孙健(ansjsun)开源的一个中文分词器,为ICTLAS的Java版本,也采用了Bigram + HMM分词模型(可参考我之前写的文章):在Bigram分词的基础上,识别未登录词,以提高 ...

  4. 深入探析 Rational AppScan Standard Edition 多步骤操作

    序言 IBM Rational AppScan Standard(下文简称 AppScan)作为面向 Web 应用安全黑盒检测的自动化工具,得到业界的广泛认可和应用.很多人使用 AppScan 时都采 ...

  5. 「C++11」Lambda 表达式

    维基百科上面对于 lambda 的引入是如下描述的: 在标准 C++,特别是当使用 C++ 标准程序库算法函数诸如 sort 和 find.用户经常希望能够在算法函数调用的附近定义一个临时的述部函数( ...

  6. 深入探析koa之中间件流程控制篇

    koa被认为是第二代web后端开发框架,相比于前代express而言,其最大的特色无疑就是解决了回调金字塔的问题,让异步的写法更加的简洁.在使用koa的过程中,其实一直比较好奇koa内部的实现机理.最 ...

  7. 开源中文分词工具探析(五):FNLP

    FNLP是由Fudan NLP实验室的邱锡鹏老师开源的一套Java写就的中文NLP工具包,提供诸如分词.词性标注.文本分类.依存句法分析等功能. [开源中文分词工具探析]系列: 中文分词工具探析(一) ...

  8. Erlang调度器细节探析

    Erlang调度器细节探析 Erlang的很多基础特性使得它成为一个软实时的平台.其中包括垃圾回收机制,详细内容可以参见我的上一篇文章Erlang Garbage Collection Details ...

  9. javaScript系列 [02]-javaScript对象探析

    [02]-javaScript对象探析 题记:多年前,以非常偶然的方式关注了微信公众号“面向对象”,本以为这个公众号主要以分享面向对象编程的干货为主,不料其乃实实在在的猿圈相亲平台.通过查看公开资料, ...

随机推荐

  1. 第十一章 Helm-kubernetes的包管理器(中)

    11.5 chart详解 chart由一系列文件组成,这些文件描述了K8s部署应用时需要的资源,比如Servcie.Deployment.PersistentVolmeClaim.Secret.Con ...

  2. 第三章 k8s cluster环境创建

    1  用如下方法安装指定版本的docker,但是我的环境会报错 # 安装rpm apt install rpm # 下载 RPM 包, docker 版本 wget https://download. ...

  3. Web api help page error CS0012: Type "System.Collections.Generic.Dictionary'2错误

    1.在asp.net Boilerplate项目中,Abp.0.12.0.2,.net framework4.5.2.下载后添加了webApi的helpPage功能,调试出现错误. dubug : a ...

  4. thinkjs 学习笔记

    抽空大概看了下thinkjs,总体感觉很不错 不了解的可以看下文档(http://thinkjs.org/doc.html) 介绍就不多说了,看下快速入门 npm install -g thinkjs ...

  5. JavaScript笔录

    JavaScript是一门编程语言,浏览器内置了JavaScript语言的解释器,所以在浏览器上按照JavaScript语言的规则编写相应代码之,浏览器可以解释并做出相应的处理. 1.JavaScri ...

  6. Tomcat官方文档关于数据源配置的内容

    虽然有网上有网友自己总结的文章,但说明得总是不够清晰,还是参考官方文档理解得比较透彻: http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html h ...

  7. A generic error occurred in GDI+的解决方案

    转自智慧光原文A generic error occurred in GDI+. 解决方法 使用image1.RotateFlip(RotateFlipType.Rotate90FlipNone)方法 ...

  8. 跟我学算法-Logistic回归

    虽然Logistic回归叫回归,但是其实它是一个二分类或者多分类问题 这里的话我们使用信用诈骗的数据进行分析 第一步:导入数据,Amount的数值较大,后续将进行(-1,1)的归一化 data = p ...

  9. Spark之 SparkSql、DataFrame、DataSet介绍

    SparkSql SparkSql是专门为spark设计的一个大数据仓库工具,就好比hive是专门为hadoop设计的一个大数据仓库工具一样. 特性: .易整合 可以将sql查询与spark应用程序进 ...

  10. java命令查询属性信息

    System.getProperty("user.home")可以查询JAVA系统的user.home属性的值, 除了user.home,还有user.dir, file.sepa ...