基本lambda语法

基本形式如下:

[capture](parameters) mutable ->return-type
{body}

[capture]:叫做捕获说明符,表示一个lambda表达式的开始能够捕获上下文中的变量共lamda函数使用。

(parameters):参数列表,即这个匿名的lambda函数的参数,如果不需要传递参数,则可以省略括号;

 mutable: mutable修饰符。默认情况下,lamda函数总是一个const函数,mutable可以取消其常量性,在使用该修饰符时,参数列表不能省略(即使参数为空)。

     ->return-type:表示返回类型,如果没有返回类型,则可以省略这部分。想知道为什么返回类型可以这么表示,这涉及到c++11的另一特性,参见自动类型推导,最后就函数体部分了。

{body}: 函数体,与普通函数的函数体一样,不过除了可以使用参数之外,还可以使用所有捕获的变量。

我们可以这样输出"hello,world"

auto func = [] () { cout <<
"hello,world"; };

func();
// now call the function

 

变量捕获与lambda闭包实现

string name;

cin >> name;

[&](){cout << name;}();

 

lambda函数能够捕获lambda函数外的具有自动存储时期的变量。函数体与这些变量的集合合起来叫闭包。

  • [] 不截取任何变量
  • [&} 截取外部作用域中所有变量,并作为引用在函数体中使用
  • [=] 截取外部作用域中所有变量,并拷贝一份在函数体中使用
  • [=, &foo] 截取外部作用域中所有变量,并拷贝一份在函数体中使用,但是对foo变量使用引用
  • [bar] 截取bar变量并且拷贝一份在函数体中使用,同时不截取其他变量
  • [x, &y] x按值传递,y按引用传递
  • [this] 截取当前类中的this指针。如果已经使用了&或者=就默认添加此选项。

看到这,不禁要问,这魔法般的变量捕获是怎么实现的呢?原来,lambda是通过创建个小类来实现的。这个类重载了操作符(),一个lambda函数是该类的一个实例。当该类被构造时,周围的变量就传递给构造函数并以成员变量保存起来。看起来跟函数对象很相似。

 

最后,lambda函数的类型是什么呢,答案是std:function。


////////////////////////////////////////////////////////////////////////////////////////////////

为什么需要lambda函数

匿名函数是许多编程语言都支持的概念,有函数体,没有函数名。1958年,lisp首先采用匿名函数,匿名函数最常用的是作为回调函数的值。正因为有这样的需求,c++引入了lambda 函数,你可以在你的源码中内联一个lambda函数,这就使得创建快速的,一次性的函数变得简单了。例如,你可以把lambda函数可在参数中传递给std::sort函数

#include <algorithm>

#include <cmath>

void abssort(float* x, unsigned N) {

std::sort(x, x + N,

// Lambda expression begins

[](float a, float b) {

return std::abs(a) < std::abs(b);

});

}

你可能会问,使用函数对象不是也可以吗?是的,函数对象当然没问题,自己写的回调函数,你可以传个函数指针也没有问题。他们有优点也有缺点。函数对象能维护状态,但语法开销大,而函数指针语法开销小,却没法保存范围内的状态。如果你觉得鱼和熊掌不可兼得,那你可错了。lambda函数结合了两者的优点,让你写出优雅简洁的代码。

2.尾置返回类型

有时候,当希望编写一个函数来接收某个序列容器中返回的一个元素的应用时候,你可能就不太能够想明白应该如何写出这个函数的返回值类型了:

template <typename T>
return_type &getItem(T begin, T end) {
return *begin; // 返回序列中一个元素的引用
}

这里的 return_type 应该怎么写呢?事实上,我们可能会想到使用 decltype() 来获得这个类型,但是,编译器在读到这个函数定义的时候,begin 甚至还没有出现,这时候我们似乎没有任何办法直接在返回类型的时候写下这个返回类型。

C++11 提供了一种新的书写返回值的方式,那就是将返回类型尾置。尾置的返回类型允许我们在参数列表之后申明返回的类型,我们的代码可以写成:

template <typename T>
auto &getItem(T begin, T end) -> decltype(*begin) {
return *begin; // 返回序列中一个元素的引用
}

其中,我们使用 decltype 告知了编译器返回类型与参数表中的返回类型相同,而 decltype 会自动推断为元素类型的引用,完成了我们的需求。


 

lamda表达式和尾置返回类型的更多相关文章

  1. C++11新语法糖之尾置返回类型

    C++11的尾置返回类型初衷是为了方便复杂函数的声明和定义,但是当复杂度稍微提升一些的时候很明显能注意到这种设计的作用微乎其微. 首先考虑如下代码: C++ //返回指向数组的指针 auto func ...

  2. C++ decltype类型说明符(尾置返回类型使用)

    转自https://blog.csdn.net/yhl_leo/article/details/50865552 1 基本语法 decltype 类型说明符生成指定表达式的类型.在此过程中,编译器分析 ...

  3. 数组的引用——用作形参&返回类型时

    一.数组的引用 切入:可以将一个变量定义成数组的引用(这个变量和数组的类型要相同) 形式: int odd[5] = {1, 3, 5, 7, 9}; int (&arr)[5] = odd; ...

  4. python 内置函数 lamda表达式。 open 文件方法

    lamda 表达式 lambda表达式 学习条件运算时,对于简单的 if else 语句,可以使用三元运算来表示,即: 普通的条件语句 if 1 == 1: name = 'kaixin' else: ...

  5. Lamda表达式学习笔记一

    Lamda表达式学习笔记一 一.Lamda语法诠释 三傻大闹宝莱坞的主人公兰彻说的一句话让我映像深刻:用简单的语言来表达同样的意 我并不是说书上的定义怎么怎么不对,而是应该理解书本上的定义,并用简单的 ...

  6. [.net 面向对象程序设计进阶] (5) Lamda表达式(一) 创建委托

    [.net 面向对象程序设计进阶] (5) Lamda表达式(一)  创建委托 本节导读: 通过学习Lambda表达式,学会创建委托和表达式目录树,深入了解Lambda的特性,让你的代码变的更加清晰. ...

  7. [.net 面向对象程序设计进阶] (6) Lamda表达式(二) 表达式树快速入门

    [.net 面向对象程序设计进阶] (6) Lamda表达式(二) 表达式树快速入门 本节导读: 认识表达式树(Expression Tree),学习使用Lambda创建表达式树,解析表达式树. 学习 ...

  8. [.net 面向对象程序设计进阶] (7) Lamda表达式(三) 表达式树高级应用

    [.net 面向对象程序设计进阶] (7) Lamda表达式(三) 表达式树高级应用 本节导读:讨论了表达式树的定义和解析之后,我们知道了表达式树就是并非可执行代码,而是将表达式对象化后的数据结构.是 ...

  9. 为了去重复,写了一个通用的比较容器类,可以用在需要比较的地方,且支持Lamda表达式

    为了去重复,写了一个通用的比较容器类,可以用在需要比较的地方,且支持Lamda表达式,代码如下: public class DataComparer<T>:IEqualityCompare ...

随机推荐

  1. day19 django继续

    上节回顾 django - 路由系统:url.py - 视图函数:views.py - 模板引擎渲染 - HttpResonse(字符串) - render(request,'index.html') ...

  2. python 异常层级

  3. 【New Feature】阿里云快照服务技术解析

    一.背景   目前上云已经成为行业发展趋势,越来越多的企业级客户将业务系统和数据库迁移到云上.而传统的备份一体机/备份软件方式,并不适合云上ECS.RDS等产品的备份与容灾服务.阿里云块存储服务提供云 ...

  4. 预警| Confluence 高危漏洞被大规模利用,阿里云WAF接入即可防护,支持免费应急服务

    2019年4月4日,阿里云安全应急响应中心监测到Confluence 官方发布安全更新指出,Widget Connector 存在服务端模板注入漏洞,攻击者能利用此漏洞实现目录穿越遍历甚至远程命令执行 ...

  5. Android BroadcastReceiver 简介

    Android BroadcastReceiver 简介  在 Android 中使用 Activity, Service, Broadcast, BroadcastReceiver     活动(A ...

  6. 2018-2-13-WPF-获得触笔悬停元素上

    title author date CreateTime categories WPF 获得触笔悬停元素上 lindexi 2018-2-13 17:23:3 +0800 2018-2-13 17:2 ...

  7. H3C 错误提示信息

  8. 将Eclipse中文注释字体变大方法

    今天下了最新的eclipse玩,结果发现注释变得灰常小,差点看瞎哥24K氪金狗眼 于是在网上找了找解决方法,结果都不对 最后自己试出来了... 方法:  Window --> Preferenc ...

  9. Spark-shell批量命令执行脚本

    #!/bin/bash source /etc/profile exec $SPARK_HOME/bin/spark-shell --queue tv --name spark-sql-test -- ...

  10. 2013年NOIP普及组复赛题解

    题目涉及算法: 计数问题:枚举: 表达式求值:栈: 小朋友的数字:动态规划: 车站分级:最长路. 计数问题 题目链接:https://www.luogu.org/problem/P1980 因为数据量 ...