c++11——lambda表达式
lambda表达式
函数式编程的一个语法,有如下优点:
(1)声明式编程风格:就地匿名定义目标函数或函数对象,不需要额外写一个命名函数或者函数对象。以更直接的方式写程序,好的可读性和可维护性。
(2)简洁:不需要额外再写一个函数或者函数对象,避免了代码膨胀和功能分散。
(3)在需要的时间和地点实现功能闭包,使程序更灵活。
lambda表达式基本概念和用法
lambda表达式定义了一个匿名函数,并且可以捕获一定范围的变量。lambda表达式的语法如下: [capture] (params) opt -> ret {body;}
其中,capture为捕获列表;params是参数表;opt为函数选项;ret为返回值类型;body是函数体。捕获列表是将lambda外部的一些变量引入lambda内部,可以为值类型或引用类型。
auto f = [] (int a) -> int {return a + 1;};
std::cout << f(1) << std::endl;
或者省略返回值类型(c++11可以进行类型推导),直接写成
auto f = [](int a){return a+1;};
std::cout << f(1) << std::endl;
捕获列表
lambda表达式可以通过捕获列表捕获一定范围内的变量:
[] 不捕获任何变量
[&] 捕获外部作用域中的所有变量,并作为引用在函数体内使用(按引用捕获)
[=] 捕获外部作用域内的所有变量,并作为副本在函数体内使用(按值捕获)
[=, &foo] 按值捕获外部作用域中的所有变量,并按引用捕获foo变量
[bar] 按值捕获bar变量,同时不捕获其他变量
[this] 捕获当前类中的this指针,让lambda表达式拥有和当前类成员函数同样的访问权限。如果已经使用了=或者&,就默认添加此项。捕获this的目的是可以在lambda中使用当前类的成员函数和成员变量。
int a = 0, b = 1;
auto f1 = []{return a;} ;//错误,没有捕获外部变量
auto f2 = [&]{return a++;};//捕获外部变量的引用,并且可以实现将a++
auto f3 = [=]{return a;};
auto f4 = [=]{return a++;};//错误,a是一个副本,并且为const类型,无法修改
auto f5 = [a, &b]{return a + (b++);}//可以,按值捕获a,并且按引用捕获b
需要注意,默认情况下,lambda表达式无法修改通过复制方式捕获的外部变量。如果希望修改这些外部变量,可以通过引用方式进行捕获,或者通过显式指明lambda表达式为mutable类型:
int a = 0;
auto f1 = [=]{return a++;};//错误
auto f2 = [=]()mutable{return a++;} //需要注意,mutable修饰的lambda即使没有参数,也要书写参数列表
int main(){
int a = 1;
auto f = [=]{return a+1; };
cout << f() << endl; //输出2
cout << "a = " << a << endl; //a = 1
auto f1 = [=]()mutable{return a++; };
cout << "a = " << a << endl; //a = 1
cout << f() << endl; //输出2 ????
cout << "a = " << a << endl; //a = 1
return 0;
}
以及需要注意lambda的延迟调用
int a = 0;auto f = [=]{return a;};a += 1;std::cout << f() << std::endl; //输出的a为之前的a
lambda表达式按值捕获外部的变量,在捕获的一瞬间,这些值就被复制到f中。
lambda表达式和闭包
在c++11中,lambda为闭包类型,是一个特殊的、匿名的非union的类类型。可以认为lambda是一个带有operator()的类,即仿函数。因此可以使用std::function和std::bind来存储和操作lambda表达式。
std::function<int(int)> f1 = [] (int a){return a;};
std::function<int(void)> f2 = std::bind([](int a){return a;}, 123);
对于没有捕获任何变量的lambda表达式,还可以被转换成一个普通的函数指针:
using func_t = int(*)(int);
func_t f = [](int a){return a;};
f(123);
可以认为lambda是一个带有operator()的类,即仿函数。按照c++的标准,lambda表达式的operator()默认是const的,因此在按值捕获的时候不能修改外部变量的值;而使用mutable可以取消 operator()的const。
就地声明和使用lambda表达式
int count = count_if(coll.begin(), coll.end(), [](int x){return x > 5 && x < 10;});
c++11——lambda表达式的更多相关文章
- C++11 lambda 表达式
C++11 新增了很多特性,lambda 表达式是其中之一,如果你想了解的 C++11 完整特性,建议去这里,这里,这里,还有这里看看.本文作为 5 月的最后一篇博客,将介绍 C++11 的 lamb ...
- C++11 lambda 表达式解析
C++11 新增了很多特性,lambda 表达式是其中之一,如果你想了解的 C++11 完整特性,建议去这里,这里,这里,还有这里看看.本文作为 5 月的最后一篇博客,将介绍 C++11 的 lamb ...
- 详解 C++11 lambda表达式
详解 C++11 lambda表达式 lambda表达式是函数式编程的基础.咱对于函数式编程也没有足够的理解,因此这里不敢胡言乱语,有兴趣的可以自己查找相关资料看下.这里只是介绍C++11中的la ...
- C++11 lambda表达式学习
lambda表达式是函数式编程的基础.咱对于函数式编程也没有足够的理解,因此这里不敢胡言乱语,有兴趣的可以自己查找相关资料看下.这里只是介绍C++11中的lambda表达式自己的认识.这里有参考文档h ...
- C++ 11 Lambda表达式
C++11的一大亮点就是引入了Lambda表达式.利用Lambda表达式,可以方便的定义和创建匿名函数.对于C++这门语言来说来说,“Lambda表达式”或“匿名函数”这些概念听起来好像很深奥,但很多 ...
- C++11 lambda表达式是如何实现的?
lambda表达式是如何实现的呢? 其实是编译器为我们了创建了一个类,这个类重载了(),让我们可以像调用函数一样使用.所以,你写的lambda表达式和真正的实现,是这个样子的: 而对于捕获变量的lam ...
- C++ 11 Lambda表达式、auto、function、bind、final、override
接触了cocos2dx 3.0,就必须得看C++ 11了.有分享过帖子:[转帖]漫话C++0x(四) —- function, bind和lambda.其实最后的Lambda没太怎么看懂. 看不懂没关 ...
- C++11 Lambda表达式简单解析
C++11 新增了非常多特性,lambda 表达式是当中之中的一个.假设你想了解的 C++11 完整特性, 建议去http://www.open-std.org/看看新标准! 非常多语言都提供了 la ...
- C++11 lambda表达式(19篇C++11文章)
C++11引入了lambda表达式,使得程序员可以定义匿名函数,该函数是一次性执行的,既方便了编程,又能防止别人的访问. Lambda表达式的语法通过下图来介绍: 这里假设我们定义了一个如上图的lam ...
随机推荐
- 【C#】AddHandler可重复多次添加事件处理器的问题
问题:在项目中发现,可以重复多次添加同一个Handler,导致触发时执行多次的问题. 这个现象也很好测试: 前台准备一个Label文本 <Label x:Name="label&quo ...
- DHCP服务器-DNS服务器-Samba服务器
DHCP服务器 DHCP在管理网络配置方面很有作用,特别是一个当一个网络的规模较大时,使用DHCP可极大的减少 管理员的工作量. DHCP分为两部分:服务端和客户端.服务端负责集中管理可动态分配的IP ...
- Redis Key 过期策略
redis 官方提供的 conf https://raw.github.com/antirez/redis/2.2/redis.conf 中6中过期策略的具体方式.redis 中的默认的过期策略是vo ...
- Yii CDbCriteria常用用法
$criteria = new CDbCriteria;$criteria->compare('name',$this->name,true,'OR'); //like部分匹配//$cri ...
- 七、CentOS 6.5 下 Nginx的反向代理和负载均衡的实现
CentOS 6.5 下 Nginx的反向代理和负载均衡的实现 * 修复上面文章的问题: 复制出一个tomcat2之后,修改service.xml文件时,要修改三个端口: 1. <!-- 800 ...
- 关于Unity中的屏幕适配
一.Game视图的屏幕分辨率可以先自定义添加,供以后选择,以下是手游经常用到的分辨率: 1.1136X640,iPhone5 2.1920X1080,横屏,主流游戏都是这个分辨率 3.1080X192 ...
- imx6 uart分析
本文主要记录: 1.uart设备注册 2.uart驱动注册 3.上层应用调用有些地方理解的还不是很透彻,希望指正. 1.uart设备注册过程 MACHINE_START(MX6Q_SABRESD, & ...
- Spring in Action 4th 学习笔记
约定: 一.@Xxx Class 表示被@Xxx注解的类.同理还有@Xxx注解的字段或方法. 例如:@Bean Method. 二.@Component Class 同时代指 @Controller. ...
- windows下安装TA-Lib库
步骤一: https://sourceforge.net/projects/ta-lib/files/ta-lib/0.4.0/ta-lib-0.4.0-msvc.zip/download?use_m ...
- 关于Random中的随机数种子Seed
Random初始化的时候,可以以一个INT32作为参数,称为seed,MSDN上的解释是:“伪随机数是以相同的概率从一组有限的数字中选取的......随机数的生成是从种子值开始......” 所有标准 ...