lambda 表达式 剖析

## 大前提:捕获列表里变量的确定时机。

捕获列表和参数列表有区别,捕获列表里的变量,是在捕获的时间点就确定了,而不是在lambda调用时确定,参数列表是在调用时才确定。所以当捕获了一个int i,i=12,然后在lambda后面的代码又改变i为22,但是当调用lambda的时候,i值还是12。

## 剖析点:

1,值捕获,即使在lambda后面改变了该值,在调用lambda时,这个值还是捕获时的值。

2,引用捕获,在lambda后面改变了该值,在调用lambda时,这个值不是捕获时的值,而是改变后的值。

3,隐式捕获:

  • [=]代表全部采用值捕获
  • [&]代表全部采用引用捕获
  • [=, &val]代表val为引用捕获,其余为值捕获
  • [&,val]代表val为值捕获,其余为引用捕获

4,可变lambda,当想在lambda函数体里,修改一个值捕获的变量是,需要mutable关键字。

5,lambda的返回类型,函数体是单一的return语句的话,可以在声明lambda时,省略返回值的类型。

### 由剖析点2:引用捕获,会引发很多血案。比如,被捕获的引用或者指针指向的对象已经不存在了,然后调用lambda时,就会出现致命错误。

警告:当以引用或者指针方式捕获一个变量时,必须保证在lambda执行时变量是存在的。

建议:

1,捕获一个普通变量时,如int, string或其他非指针类型,通常可以采用简单的值捕获方式。所以,只需关注变量在捕获时,值是否是所需的值就行。

2,如果捕获一个指针或迭代器,或引用,就必须保证在lambda被执行的时候,绑定到迭代器,指针或引用的对象仍然存在,而且,需要保证对象是预期的值。因为,有可能在捕获的时候,是预期的值,但是在执行lambda之前有代码改变了绑定对象的值,在执行lambda时,就变成不是预期的值了。

3,一般来说,尽量减少捕获的数据量,来避免潜在的捕获导致的问题。而且,如果可能的话,尽量避免捕获指针或引用。

#include <iostream>
#include <vector>
#include <algorithm> using namespace std; int main(){
//test1 值捕获
/*
int i = 1;
auto f = [i]{return i;};
i = 10;
int j = f();
cout << j << endl;
*/ //test2 引用捕获
/*
int i = 1;
auto f = [&i]{return i;};
i = 10;
int j = f();
cout << j << endl;//3
*/ //test3 隐式值捕获
/*
int i = 1;
int j = 2;
auto f = [=]{return i + j;};
i = 3;
int m = f();
cout << m << endl;
*/ //test4 隐式引用捕获
/*
int i = 1;
int j = 2;
auto f = [&]{return i + j;};
i = 3;
int m = f();
cout << m << endl;//5
*/ //test5 隐式,显式混合1
/*
int i = 1;
int j = 2;
//i为值捕获,j为引用捕获
auto f = [=,&j]{return i + j;};
i = 3;
int m = f();
cout << m << endl;//3
*/ //test5 隐式,显式混合2
/*
int i = 1;
int j = 2;
//i为引用捕获,j为值捕获
auto f = [&,j]{return i + j;};
i = 3;
int m = f();
cout << m << endl;//5
*/ //test6 可变lambda
/*
int i = 10;
auto f = [i] () mutable{return ++i;};
int j = f();
cout << j << endl;
*/
/*
const int i = 10;
//编译错误,因为i为const
auto f = [i] () mutable{return ++i;};
int j = f();
cout << j << endl;
*/ //test7 lambda的返回类型
vector<int> ivec{-12,2,-22,3,0};
//改变ivec里的值,负数变成整数
//此lambda不写返回类型没有问题.
//transform(ivec.begin(),ivec.end(),ivec.begin(),
// [](int i){return i < 0 ? -i : i;});
//此lambda不写返回类型也没有问题.
transform(ivec.begin(),ivec.end(),ivec.begin(),
[](int i){if(i < 0) return -i;
else return i;});
for(const auto &s : ivec){
cout << s << " ";
}
cout << endl;
}

c/c++ 学习互助QQ群:877684253

本人微信:xiaoshitou5854

c/c++ lambda 表达式 剖析的更多相关文章

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

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

  2. Lambda表达式(C语言-gcc编译器)

    前言 先来啰嗦几句,身边的朋友,同事都喜欢在博客上记录自己在学习计算机编程技术路程上的一些问题和心得.就我个人而言,这是个好习惯,特别是在计算机编程领域,技术方向种类繁多,永无止境.所以,我也开始我人 ...

  3. java8 Lambda表达式的新手上车指南(1)

    背景 java9的一再推迟发布,似乎让我们恍然想起离发布java8已经过去了三年之久,java8应该算的上java语言在历代版本中变化最大的一个版本了,最大的新特性应该算得上是增加了lambda表达式 ...

  4. java8 Lambda表达式的新手上车指南(1)--基础语法和函数式接口

    背景 java9的一再推迟发布,似乎让我们恍然想起离发布java8已经过去了三年之久,java8应该算的上java语言在历代版本中变化最大的一个版本了,最大的新特性应该算得上是增加了lambda表达式 ...

  5. 浅入浅出Lambda表达式

    大家在开发中会经常看到也会经常使用lambda表达式. 园子里也有很多详解lambda表达式的文章,多是从横向来讲述. 但lambda表达式到底如何变成现在这个样子,表达式的形式到底代表什么含义,这些 ...

  6. c#封装DBHelper类 c# 图片加水印 (摘)C#生成随机数的三种方法 使用LINQ、Lambda 表达式 、委托快速比较两个集合,找出需要新增、修改、删除的对象 c# 制作正方形图片 JavaScript 事件循环及异步原理(完全指北)

    c#封装DBHelper类   public enum EffentNextType { /// <summary> /// 对其他语句无任何影响 /// </summary> ...

  7. 你知道C#中的Lambda表达式的演化过程吗?

    那得从很久很久以前说起了,记得那个时候... 懵懂的记得从前有个叫委托的东西是那么的高深难懂. 委托的使用 例一: 什么是委托? 个人理解:用来传递方法的类型.(用来传递数字的类型有int.float ...

  8. Linq表达式、Lambda表达式你更喜欢哪个?

    什么是Linq表达式?什么是Lambda表达式? 如图: 由此可见Linq表达式和Lambda表达式并没有什么可比性. 那与Lambda表达式相关的整条语句称作什么呢?在微软并没有给出官方的命名,在& ...

  9. 背后的故事之 - 快乐的Lambda表达式(一)

    快乐的Lambda表达式(二) 自从Lambda随.NET Framework3.5出现在.NET开发者眼前以来,它已经给我们带来了太多的欣喜.它优雅,对开发者更友好,能提高开发效率,天啊!它还有可能 ...

随机推荐

  1. MyEclipse 皮肤、主题、背景色

    第一步:打开myeclipse--->help--->install from site--->Add将路径粘贴在这里.等待安装颜色主题.https://raw.github.com ...

  2. (2)编译安装lamp三部曲之mysql-技术流ken

    简介 采用yum安装lamp简单,快捷,在工作中也得到了普遍应用.但是如果我们需要某些特定模块功能,以及制定安装位置等,就需要用到编译安装了,接下来将编译安装lamp之mysql. mysql的简介网 ...

  3. lambda,linq

    一:什么是Lambda表达式 lambda表达式是实例化委托的一个参数,就是一个方法,具体实现如下: { //.NetFramework 1.0-1.1的时候这样应用 NoReturnNoPara m ...

  4. NPOI导出EXCEL报_服务器无法在发送 HTTP 标头之后追加标头

    虽然发表了2篇关于NPOI导出EXCEL的文章,但是最近再次使用的时候,把以前的代码粘贴过来,居然报了一个错误: “服务器无法在发送 HTTP 标头之后追加标头” 后来也查询了很多其他同学的文章,都没 ...

  5. 一个简单的Code First建立

    1]从VS中建立一个mvc程序 记得添加NuGet包 然后在web.config中添加链接数据库的语句 <connectionStrings> <add name="Ent ...

  6. IIS Tomcat共享80端口

    为什么有这种需求, 原因是这样的, 公司有一个Java的web项目,在另一台服务器A上,最近老板一时兴起,想把他合并到这台稳定点的服务器B上,服务器B上使用IIS来寄宿asp.net 网站, 怎么办呢 ...

  7. 设计模式—装饰模式的C++实现

    这是Bwar在2009年写的设计模式C++实现,代码均可编译可运行,一直存在自己的电脑里,曾经在团队技术分享中分享过,现搬到线上来. 1. 装饰模式简述 1.1 目的 动态地给一个对象添加一些额外的职 ...

  8. 用Python实现Zabbix-API 监控

    做运维的朋友应该知道,公司IDC机房经常有上架.下架.报修和报废的服务器.如果服务器数量很多的时候很容易造成监控遗漏.       大的互联网公司把监控系统和CMDB(资产管理系统|配置管理数据库系统 ...

  9. 1.创建和销毁对象_EJ

    在这里记录<Effective Java>学习笔记.该书介绍了java编程中70多种极具实用价值的经验规则,揭示了该做什么,不该做什么才能产生清晰.健壮和高效的代码. 第1条: 考虑用静态 ...

  10. Github被微软收购,这里整理了16个替代品

    微软斥资75亿美元收购以后,鉴于微软和开源竞争的历史,很多开发者都感到惊恐.毕竟,互联网上最大的一块可以自由的净土被微软染指,宝宝不开森.如果你真的担心微软会对Github有所动作,那么这里我列举了1 ...