c/c++ lambda 表达式 剖析

时间:2022-09-06 10:44:54

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&plus;&plus;11新特性&lpar;3&rpar; lambda表达式&lpar;1&rpar;

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

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

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

  3. java8 Lambda表达式的新手上车指南&lpar;1&rpar;

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

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

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

  5. 浅入浅出Lambda表达式

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

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

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

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

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

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

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

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

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

随机推荐

  1. 几个不错的webgl教程网

    http://ogldev.atspace.co.uk/index.html http://www.opengl-tutorial.org/ http://blog.wysaid.org/catego ...

  2. php判断是否为微信浏览器访问

    今天遇到个问题,就是需要判断是否在微信浏览器内访问: if (strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false) {    ...

  3. Linux学习——shell编程之环境变量配置文件

    小白学习,在学习中总结! shell编程之环境变量配置文件 一:环境变量配置文件 1 shell编程之环境变量配置 变量类型: 用户自定义变量(本地变量) 环境变量 :定义每个用户的操作环境,如pat ...

  4. 翻译连载 &vert; 第 11 章:融会贯通 -《JavaScript轻量级函数式编程》 &vert;《你不知道的JS》姊妹篇

    原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...

  5. ABP中的拦截器之AuditingInterceptor

    在上面两篇介绍了ABP中的ValidationInterceptor之后,我们今天来看看ABP中定义的另外一种Interceptor即为AuditingInterceptor,顾名思义就是一种审计相关 ...

  6. EE4218 &sol; EE4216 Faculty of Science and Engineering

    Faculty of Science and EngineeringDepartment of Electronic and ComputerEngineeringEnd of Semester As ...

  7. everything结果出现文件找不到

    点击“工具”——“选项”——“索引”——“强制重建”——“确定”, 然后重启everything即可.

  8. MySQL查询语句执行过程及性能优化-查询过程及优化方法(JOIN&sol;ORDER BY)

    在上一篇文章MySQL查询语句执行过程及性能优化-基本概念和EXPLAIN语句简介中介绍了EXPLAIN语句,并举了一个慢查询例子:

  9. Web API设计方法论

    英文原文:A Web API Design Methodology 为Web设计.实现和维护API不仅仅是一项挑战:对很多公司来说,这是一项势在必行的任务.本系列将带领读者走过一段旅程,从为API确定 ...

  10. 搜狐视频Redis私有云平台CacheCloud

    一.CacheCloud是做什么的 CacheCloud提供一个Redis云管理平台:实现多种类型(Redis Standalone.Redis Sentinel.Redis Cluster)自动部署 ...