C++培训 lambda

  多的不说,还是介绍的C++11新特性,一下介绍的是:C++11 新特性之 lambda

  不想看toy code的读者可以直接拉到文章最后看这部分的总结。

  lambda 简介

  熟悉Python的程序员应该对lambda不陌生。简单来说,lambda就是一个匿名的可调用代码块。在C++11新标准中,lambda具有如下格式:

  [capture list] (parameter list) -> return type { function body }

  可以看到,他有四个组成部分:

  capture list: 捕获列表

  parameter list: 参数列表

  return type: 返回类型

  function body: 执行代码

  其中,参数列表和返回类型可以忽略。

  下面,具体看几个简单的例子:

  auto f1 = [] { return 1; };

  auto f2 = [] () { return 2; };

  cout<

  捕获列表

  lambda中的捕获列表既可以捕获值,也可以捕获引用。

  捕获值:

  int test_data[] = {1, 5, 9, 7, 3, 19, 13, 17};

  int border = 8;

  auto f3 = [border](const int &i){ if(i > border) cout<

  for_each(begin(test_data), end(test_data), f3);

  cout<

  捕获引用:

  auto f4 = [&border](const int &i){ if(i > border) cout<

  border = 6;

  for_each(begin(test_data), end(test_data), f4);

  cout<

  通过输出可以看出,lambda中起作用的border是修改后的6,证实了捕获的确是是引用。

  需要注意的是,在捕获引用时,需要保证当lambda被调用时,此引用仍然有效。

  捕获列表还可以采用隐式捕获的方式,即让编译器通过lambda的执行代码来判断需要捕获哪些局部变量。

  隐式捕获可以捕获值、引用或者两者混合:

  char space = ‘ ‘;

  auto f5 = [=](const int &i){ if(i > border) cout<

  auto f6 = [&](const int &i){ if(i > border) cout<

  auto f7 = [&, space](const int &i){ if(i > border) cout<

  border = 0;

  for_each(begin(test_data), end(test_data), f5);

  cout<

  for_each(begin(test_data), end(test_data), f6);

  cout<

  for_each(begin(test_data), end(test_data), f7);

  cout<

  这里的f7使用的混合形式,可以读作“除了space捕获值之外,其他变量均捕获引用”。

  可变 lambda

  当lambda需要在其中修改被值捕获的变量的值时,需要给lambda加上mutable关键字。否则会有编译错误。

  auto f8 = [&, space](const int &i) mutable { if(i > border) {cout<

  for_each(begin(test_data), end(test_data), f8);

  cout<

  cout<<1<

  从输出中可以看出,space在lambda f8中的值,在第一次调用之后,就被变成了制表符Tab;但是在lambda之外,space仍然是空格。

  返回类型

  lambda的返回类型采用尾置返回类型的方式。一般的:

  lambda如果只包含return语句,则编译器可以推断其返回类型,此时可以不显示指定返回类型;

  否则,编译器假定lambda返回void,而返回void的函数不可以反悔任何具体值,这在大多数情况下是个矛盾,因此需要显示指定返回类型。

  但是,经过实际测试,目前的g++编译器更聪明了:对于第2点,目前只要编译器可以从lambda函数体中推断出函数的返回类型,就不需要显式指定返回类型,例如:

  auto f9 = [](const int i){if(i % 3) return i * 3; else return i;};

  transform(begin(test_data), end(test_data), begin(test_data), f9);

  border = 0;

  for_each(begin(test_data), end(test_data), f6);

  cout<

  lambda代码块中有多个return语句,并且还有if/else语句,但是编译器可以根据return语句推断出,其返回值应该是一个int类型,所以可以省略尾置返回类型。

  但是,像下面这种形式,由于编译器在推断返回类型时发现了不一致,所以必须显式的指定返回类型:

  auto f10 = [](const int i) -> double

  {if(i % 5) return i * 5.0; else return i;};

  transform(begin(test_data), end(test_data), begin(test_data), f10);

  for_each(begin(test_data), end(test_data), f6);

  cout<

  总结

  lambda表达式形式: [capture list] (parameter list) -> return type { function body },其中parameter list和return type可以省略。

  捕获列表可以捕获值[val],也可以捕获引用[&ref]。

  捕获列表还可以隐式捕获局部变量,同样有捕获值[=]和捕获引用[&]两种方式,初次之外还可以混合捕获[&, val]或者[=, &ref]。

  当lambda需要修改捕获的值时,需要加上mutable关键字。

  当lambda无法自动推断出返回值类型时,需要通过尾置返回类型的方式显示指定。

本文摘自:http://www.cdtedu.com/c/course/8138.html如需转载,请保存!

时间: 2024-11-13 06:46:25

C++培训 lambda的相关文章

C#中的Lambda表达式和表达式树

在C# 2.0中,通过方法组转换和匿名方法,使委托的实现得到了极大的简化.但是,匿名方法仍然有些臃肿,而且当代码中充满了匿名方法的时候,可读性可能就会受到影响.C# 3.0中出现的Lambda表达式在不牺牲可读性的前提下,进一步简化了委托. LINQ的基本功能就是创建操作管道,以及这些操作需要的任何状态.这些操作表示了各种关于数据的逻辑,例如数据筛选,数据排序等等.通常这些操作都是用委托来表示.Lambda表达式是对LINQ数据操作的一种符合语言习惯的表示方式. Lambda表达式不仅可以用来创

赣南师范学院数学竞赛培训第10套模拟试卷参考解答

1. 设 $f,g$ 是某数域上的多项式, $m(x)$ 是它们的首一最小公倍式, 而 $\scrA$ 为该数域上某线性空间 $V$ 的一个线性变换. 试证: $$\bex \ker f(\scrA)+\ker g(\scrA)=\ker m(\scrA). \eex$$ 证明: 先证: $\ker f(\sigma)+\ker g(\sigma)\subset\ker m(\sigma).$ 由 $f|m$, $g|m$ 知 $\ker f(\sigma)\subset \ker m(\sig

Lambda表达式实战视频教程

视频教程地址: https://my.oschina.net/u/3217554/blog/1507456 1:Lambda表达式及函数式接口介绍 2:Lambda表达式详解 3:方法的引用(一) 4:方法的引用(二) 5:Stream API(一) 6:Stream API(二) 7:Lambda表达式.方法的引用.Stream API实战

lambda表达式封装对数据库的查询

前言: 1.为什么要封装lambda表达式数据库查询,原因有一下几点: 1.1.在以往的开发中进行数据库表查询时,其实所需要的字段就是其中几个,但是在开发中,开发者往往习惯select * 进行查询,当数据多和用户量多时,查询的效率会降低. 1.2.在写查询where条件的时候,总是用string.format去拼接字符串,开发效率低. 1.3.代码不够优雅,代码中嵌套和多sql语句,如果是表字段发生改变时编译器检查不出来,代码出错的概率大. 1.4.本着 write less  do more

Lambda表达式

import org.junit.Test; import java.util.Comparator; import java.util.function.Consumer; /** * 一.Lambda 表达式基础语法:Java8中引入一个新的操作符"->"该操作符称为箭头操作符或Lambda操作符 * 箭头操作符将Lambda表达式拆分为两部分: * 左侧: Lambda表达式的参数列表 * 右侧: Lambda表达式中所需要执行的功能,即Lambda体 * * 语法格式一:

第一天的培训

今天是我们培训的第一天,作为初入IT类型的学习,讲师给我们说了很多,关于它的发展时间,前景还有许多他自身所经历的,但是毕竟是第一天,给我们讲的是让我们有个大概的了解和方向.当初对培训机构抱有很多疑问,虽然口口声声说的是可以给分配工作,可我对这里能学到的知识和能用到的方向更加期待,毕竟谁都希望自己以后的工作成果能得到更多人的使用和赞同,以及能有个长远的发展前景.      第一天的课程基本算是以熟悉这个行业为主吧,没有什么可以写的,以后估计就会是每天学习内容的总结或者是理解,将会有一堆的代码吧.希

Oracle SQL语言基础及环境准备_超越OCP精通Oracle视频教程培训26

Oracle SQL语言基础及环境准备_超越OCP精通Oracle视频教程培训26 本课程介绍: Oracle视频教程,风哥本套oracle教程培训是<<Oracle数据库SQL语言实战培训教程>>的第1/5套:SQL语言之基础入门及环境准备.主要学习Oracle数据库SQL语言基础介绍.PL/SQL语言介绍.数据库SQL对象与数据类型介绍.SQL语言实战环境准备等. Oracle SQL语言之基础及环境准备,课程内容详细如下: Oracle数据库SQL语言基础介绍Oracle数据

Oracle SQL语言DDL和对象管理_超越OCP精通Oracle视频教程培训27

Oracle SQL语言DDL和对象管理_超越OCP精通Oracle视频教程培训27 本课程介绍: Oracle视频教程,风哥本套oracle教程培训是<<Oracle数据库SQL语言实战培训教程>>的第2/5套:Oracle SQL语言DDL和对象管理.主要学习Oracle数据库模式对象和表中可用的数据类型,表/临时表的创建与使用,索引/约束的创建与管理,视图/同义词/序列的创建和使用,触发器/存储过程/包的创建和使用. Oracle SQL语言DDL和对象管理,课程内容详细如下

Oracle SQL语言DML语句与事务_超越OCP精通Oracle视频教程培训28

Oracle SQL语言DML语句与事务_超越OCP精通Oracle视频教程培训28 本课程介绍: Oracle视频教程,风哥本套oracle教程培训是<<Oracle数据库SQL语言实战培训教程>>的第3/5套:Oracle SQL语言DML语句与事务.主要学习Oracle数据库SQL语句INSERT命令,学习使用UPDATE命令,学习使用DELETE命令,学习创建PL/SQL对象,事务概念与控制,锁的检测和锁争用,了解撤销数据. Oracle SQL语言DML语句与事务管理,课