C++11之Lambda特性探析
目录
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特性探析的更多相关文章
- 【C++11】新特性——Lambda函数
本篇文章由:http://www.sollyu.com/c11-new-lambda-function/ 文章列表 本文章为系列文章 [C++11]新特性--auto的使用 http://www.so ...
- 浏览器环境下JavaScript脚本加载与执行探析之defer与async特性
defer和async特性相信是很多JavaScript开发者"熟悉而又不熟悉"的两个特性,从字面上来看,二者的功能很好理解,分别是"延迟脚本"和"异 ...
- 开源中文分词工具探析(三):Ansj
Ansj是由孙健(ansjsun)开源的一个中文分词器,为ICTLAS的Java版本,也采用了Bigram + HMM分词模型(可参考我之前写的文章):在Bigram分词的基础上,识别未登录词,以提高 ...
- 深入探析 Rational AppScan Standard Edition 多步骤操作
序言 IBM Rational AppScan Standard(下文简称 AppScan)作为面向 Web 应用安全黑盒检测的自动化工具,得到业界的广泛认可和应用.很多人使用 AppScan 时都采 ...
- 「C++11」Lambda 表达式
维基百科上面对于 lambda 的引入是如下描述的: 在标准 C++,特别是当使用 C++ 标准程序库算法函数诸如 sort 和 find.用户经常希望能够在算法函数调用的附近定义一个临时的述部函数( ...
- 深入探析koa之中间件流程控制篇
koa被认为是第二代web后端开发框架,相比于前代express而言,其最大的特色无疑就是解决了回调金字塔的问题,让异步的写法更加的简洁.在使用koa的过程中,其实一直比较好奇koa内部的实现机理.最 ...
- 开源中文分词工具探析(五):FNLP
FNLP是由Fudan NLP实验室的邱锡鹏老师开源的一套Java写就的中文NLP工具包,提供诸如分词.词性标注.文本分类.依存句法分析等功能. [开源中文分词工具探析]系列: 中文分词工具探析(一) ...
- Erlang调度器细节探析
Erlang调度器细节探析 Erlang的很多基础特性使得它成为一个软实时的平台.其中包括垃圾回收机制,详细内容可以参见我的上一篇文章Erlang Garbage Collection Details ...
- javaScript系列 [02]-javaScript对象探析
[02]-javaScript对象探析 题记:多年前,以非常偶然的方式关注了微信公众号“面向对象”,本以为这个公众号主要以分享面向对象编程的干货为主,不料其乃实实在在的猿圈相亲平台.通过查看公开资料, ...
随机推荐
- docker 学习(十) 容器常用命令
1 docker run -it ubuntu:15.10 /bin/bash 如果有ubuntu:15.10这个镜像,就run,否则会从dockerhub下载,并run. -it 一般连用,表示按 ...
- 【POJ】3616 Milking Time(dp)
Milking Time Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10898 Accepted: 4591 Des ...
- 【BZOJ】4721: [Noip2016]蚯蚓 / 【洛谷】P2827 蚯蚓(单调队列)
Description 本题中,我们将用符号[c]表示对c向下取整,例如:[3.0」= [3.1」=[3.9」=3.蛐蛐国最近蚯蚓成灾了!隔壁跳 蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮 ...
- 初识python(python的安装与运行)
python--“优雅”.“明确”.“简单”的哲学定位 一.python的安装(Windows环境下) 1.在python官网下载安装文件 python的官方网址:https://www.python ...
- 常见的HTTP Header
文件信息: Content-Type: application/x-javascript Content-Length: 2000 Content-Type:指定请求和响应的内容类型,如果未指定即为t ...
- Arduino学习笔记A6(补充) - 在串口读取多个字符串,并且转换为数字数组
功能如题目. 在串口收到逗号分割的6串数字比如 100,200,45,4,87,99 然后在6个PWM端口3, 5, 6, 9, 10, 11输出对应PWM值 代码注释很详细了,就不再说明了. ARD ...
- YUV图像合成原理<转>
YUV图像合成原理 引言:在视频监控中最常用的就是图像拼接和字符叠加,25FPS的视频流,如果每隔40MS就从各个通道中取一幅图像来合成,则可以看到一个实时的合成视频.合成的过程也就是原始图像的拼接. ...
- Mysql 性能优化 ( my.cnf )
简介: Mysql 参数优化 一.Mysql 源码编译参数 shell > yum -y install gcc gcc-c++ make cmake ncurses-devel zlib-de ...
- Spring IOC基础
2.1.1 IOC是什么IOC—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想.在Java开发中,IOC意味着将你设计好的对象交给容器控制,而不是传统的在你的 ...
- C# ValueTypes
[C# ValueTypes] 1.哪些类型是ValueType? The value types consist of two main categories: Structs Enumeratio ...