写过c#之后,觉得c#里的lambda表达式和delegate配合使用,这样的机制用起来非常爽。c++11也有了lambda表达式,形式上有细小的差异。形式如下:

  c#:(input parameters) => {statement;}

  c++:[capture list](parameter list) -> return type {statement;}

  c++lambda表达式共分为4各部分。其中parameter list 和 return type 是可以在特定情况下省略的。

一、capture list

  capture list的作用是捕获lambda所在函数的局部变量。其中捕获的类型可以分为值捕获,引用捕获和隐式捕获。

  值捕获:

 void fun()
{
int a = 1;
auto f = [a] { return a; };
a = ;
auto r = f();
cout << r << endl;
}

  结果是1。 和函数值传递一样,行4 lambda表达式捕获的v1是fun函数中局部变量a的一份拷贝,因此行5改变了a并不影响 lambda表达式内的a。

  引用捕获:

 void fun()
{
int a = ;
auto f = [&a] { return a; };
a = 0;
auto r = f();
cout << r << endl;
}

  结果为0,行4 捕获的是a对象本身。但是值得一提的是采用引用捕获要保证lambda表达式工作时,引用的变量还是要存在的。

  隐式捕获:

  隐式捕获的方式,就是capture的列表可以用'='和'&'代替,让编译器隐式的推断你使用的是那个变量,然后这两个字符表示捕获的类型‘=’表示值捕获,'&'是引用捕获。采用隐式捕获的方式上述两段代码的行4可以分别表示为:

  auto f = [=] {return a;}

  auto f = [&] {return a;}

  如果需要,你也可以选择混合使用这几种方式:

  

 void fun()
{
int a = ;
int b = ;
int c = ;
auto f = [&,a]{cout << "a = " << a << " b=" << b << " c=" << c;};
a++;
8 b++;
9 c++;
f();
}

  输出结果 : a = 1 b=3 c=4

  不难发现 b,c都是采用的引用捕获的方式而a采用的值捕获的方式。隐式捕获是这样工作的:对于['=' or '&',capture list or null ]这样捕获列表 ,parameter 是非必须的,相当于对前一种情况的特化(例如template特化那样)。即,如果前一个位置采用了‘=’,capture list可以选择那些需要引用捕获的局部变量或者为空(但是不可以也是值捕获的局部变量)。‘&’同理。

二、parameter list

  大体来说parameter list用法和普通的函数类似。c++11标准规定lambda表达式不可以有默认参数,但是我在g++ 4.8 和vs2013分别测试如下代码,g++能通过并且给出期望的结果,vs2013报错说lambda表达式不可以有默认参数。显然g++对c++11进行了扩展,为了代码的可移植性,我们还是应该严格遵守标准。

  具体参考c++11文档:5.1.2.5 节:

  The closure type for a lambda-expression has a public inline function call operator (13.5.4) whose param- eters and return type are described by the lambda-expression’s parameter-declaration-clause and trailing- return-type respectively. This function call operator is declared const (9.3.1) if and only if the lambda- expression’s parameter-declaration-clause is not followed by mutable. It is neither virtual nor declared volatile. Default arguments (8.3.6) shall not be specified in the parameter-declaration-clause of a lambda- declarator. Anyexception-specificationspecifiedonalambda-expressionappliestothecorrespondingfunction call operator. An attribute-specifier-seq in a lambda-declarator appertains to the type of the corresponding function call operator.

 int fun()
{
auto f = [](string s1,string s2){cout << s1 << s2;};
f("hello ","world\n");
auto f2 = [](string s1,string s2="hahah\n"){cout << s1 << s2;};
f2("eric ");
}

三、return type

  lambda- declarator 中 返回类型也必须是c++11的尾置返回类型(trailing return type)。并且可以省略,可以交给编译器去推断。(vs2013和g++在lambda体使用了if时皆可以推断出返回类型,当然每个if-else分支返回的类型应该统一,否则需要加上位置返回类型的声明)。

四、mutable

  在lambda表达式的parameter list 和 return type之间加上关键词 mutable ,表示 捕获的值可以在{}中改变,而默认情况捕获的值是不允许改变的(但是捕获的引用是可以改变的)。或许是为了效率,不加mutable的之前的值捕获,可以少开辟一些内存,只有加上mutable之后才真正的为捕获的值分配内存。

c++11 新特性之lambda表达式的更多相关文章

  1. C++11新特性之一——Lambda表达式

    C++11新特性总结可以参考:http://www.cnblogs.com/pzhfei/archive/2013/03/02/CPP_new_feature.html#section_6.8 C++ ...

  2. C++11新特性(3) lambda表达式(1)

    C++11加入了一项名为lambda表达式的新功能.通过这项功能能编写内嵌的匿名函数,而不必编写独立函数或函数对象,使得代码更加理解. lambda表达式包括下面部分. [capture_block] ...

  3. C++11 新特性:Lambda 表达式

    参考文章:https://blogs.oracle.com/pcarlini/entry/c_1x_tidbits_lambda_expressions 或许,Lambda 表达式算得上是 C++ 1 ...

  4. C++11 新特性之 Lambda表达式

    lambda表达式能够用于创建并定义匿名的函数对象,以简化编程工作 Lambda的语法例如以下: [函数对象參数](操作符重载函数參数)->返回值类型{函数体} []内的參数指的是Lambda表 ...

  5. java8新特性: lambda表达式:直接获得某个list/array/对象里面的字段集合

    java8新特性: lambda表达式:直接获得某个list/array/对象里面的字段集合 比如,我有一张表: entity Category.java service CategoryServic ...

  6. Java8 新特性学习 Lambda表达式 和 Stream 用法案例

    Java8 新特性学习 Lambda表达式 和 Stream 用法案例 学习参考文章: https://www.cnblogs.com/coprince/p/8692972.html 1.使用lamb ...

  7. JDK1.8新特性(一) ----Lambda表达式、Stream API、函数式接口、方法引用

    jdk1.8新特性知识点: Lambda表达式 Stream API 函数式接口 方法引用和构造器调用 接口中的默认方法和静态方法 新时间日期API default   Lambda表达式     L ...

  8. Java8新特性之Lambda表达式

    lambda表达式是java8给我们带来的几个重量级新特性之一,借用lambda表达式,可以让我们的java程序设计更加简洁.最近新的项目摒弃了1.6的版本,全面基于java8进行开发,本文是java ...

  9. 夯实Java基础(二十二)——Java8新特性之Lambda表达式

    1.前言 Java 8于14年发布到现在已经有5年时间了,经过时间的磨练,毫无疑问,Java 8是继Java 5(发布于2004年)之后的又一个非常最重要的版本.因为Java 8里面出现了非常多新的特 ...

随机推荐

  1. 开源日志记录工具log4j

    前言:当我们进行大的项目书写的时候或者我们选择维护程序的时候,想知道几点几时我们录入的数据有bug是那么我们就采用--------------------------->log4j记录日志的信息 ...

  2. excel查看VBA代码快捷键

    公司现在的很多自动化代码生成使用excel VBA,本来这事跟自己一点关系打不着,不过计划年底切换中间件,这得导致部分代码结构调整,自己还得去调整测试,老忘掉这快捷键,特记录下,Alt + F11

  3. java RSA加解密以及用途

    在公司当前版本的中间件通信框架中,为了防止非授权第三方和到期客户端的连接,我们通过AES和RSA两种方式的加解密策略进行认证.对于非对称RSA加解密,因为其性能耗费较大,一般仅用于认证连接,不会用于每 ...

  4. SSH免密码登录过程解析和实现

    SSH 为建立在应用层和传输层基础上的安全协议.SSH 是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议.利用SSH 协议可以有效防止远程管理过程中的信息泄露问题. 从客户端来看,SSH提 ...

  5. ENVI【非监督分类】

    非监督分类的概念: 非监督分类,又称“聚类分析或者点群分析”.在多光谱图像中搜寻.定义其自然相似光谱集群的过程.它不必对图像地物获取先验知识,仅依靠图像上不同地物光谱信息进行特征提取,在统计特征的差别 ...

  6. Spring(3)—— Junit框架单元测试

    Junit主要用于单元测试,即白盒测试.它是一个开源的由JAVA开发的一个用于测试的框架. Junit的几个基本概念:TestCase,TestSuite,TestFixtrue TestCase:代 ...

  7. 微信 小程序 drawImage wx.canvasToTempFilePath wx.saveFile 获取设备宽高 尺寸问题

    以下问题测试环境为微信开发者0.10.102800,手机端iphone6,如有不对敬谢指出. 根据我的测试,context.drawImage,在开发者工具中并不能画出来,只有预览到手机中显示. wx ...

  8. sharepoint2010如何本地化WebPart的Category、WebDisplayName 和 WebDescription 属性

    在项目中经常需要实现多语言其中包括webpart的属性也需要.那么如何实现呢? 首先需要资源文件,利用资源文件实现语言的翻译,如下图: 创建好资源后,下面我们来实现webpart属性的多语言.方法代码 ...

  9. c中的函数

    一. 什么是函数 l 任何一个C语言程序都是由一个或者多个程序段(小程序)构成的,每个程序段都有自己的功能,我们一般称这些程序段为“函数”.所以,你可以说C语言程序是由函数构成的. l 比如你用C语言 ...

  10. 自定义button

    改变button内部label和imageView的frame - (CGRect)titleRectForContentRect:(CGRect)contentRect - (CGRect)imag ...