lambda表达式是函数式编程的基础。咱对于函数式编程也没有足够的理解,因此这里不敢胡言乱语,有兴趣的可以自己查找相关资料看下。这里只是介绍C++11中的lambda表达式以及与此相关的闭包(closure)。

其次,给出两个例子,可以看出lambda表达式的写法

[](int x, int y) { return x + y; }

[](int x, int y) -> int { int z = x + y; return z + x; }   //表明返回值类型是int型

也就是说,一个lambda表达式很类似于普通的函数定义的写法,区别在于三点,一是没有函数名(你也可以认为函数名是[]),二是这个函数没有普通函数那样的返回值类型,返回值类型的写法在第2行,即在参数列表与函数定义之间以箭头写明,三是在参数列表之前有一个[] (其实这里还可能有更多的形式,后面会说)

第三,lambda表达式的标准形式是什么?

如下。这里先只是列出,后面会详细解释。

lambda-expression:
  lambda-introducer lambda-declaratoropt compound-statement
lambda-introducer:
  [ lambda-captureopt ]

lambda-capture:
  capture-default
  capture-list
  capture-default , capture-list
capture-default:
  &
  =
capture-list:
  capture
  capture-list , capture
capture:
  identifier
  & identifier
  this
lambda-declarator:
  ( parameter-declaration-clause ) attribute-specifieropt mutableopt exception-specificationopt trailing-return-typeopt

第四,进一步的分析

上面的标准形式中,最不好理解的可能就是lambda-capture了。其实它对应的就是闭包的概念,而作用是描述外部传入的参数。

wiki上有一个例子,如下

 
std::vector<int> someList;
int total = 0;
std::for_each(someList.begin(), someList.end(), [&total](int x) {
total += x;
});
std::cout << total;
 

这段代码做的事情是把someList中的所有变量求和。其中定义的lambda函数如下,

[&total](int x) {total += x;}

与前面的例子不同,这里的lambda-introducer是[&total]而不是之前的[]。这么写的作用是,在这个lambda函数中以引用方式使用外部变量total,这样求和结果就可以存放于这个变量中。那么类似的,还可以以传值方式使用外部变量,写成[total]就可以,而且,如果需要用到的外部变量较多,可以有简略的写法。一个完整的列表如下(来自wiki,这里我把他们翻译成我们比较习惯的表述形式)

 
[] // 没有定义任何变量。使用未定义变量会导致错误。
[x, &y] // x 以传值方式传入(默认),y 以引用方式传入。
[&] // 任何被使用到的外部变量皆隐式地以引用方式加以使用。
[=] // 任何被使用到的外部变量皆隐式地以传值方式加以使用。
[&, x] // x 显示地以传值方式加以使用。其余变量以引用方式加以使用。
[=, &z] // z 显示地以引用方式加以使用。其余变量以传值方式加以使用。
 

第五,代码练习及验证

c++ 将lambda表达式作为参数传递
、获取变量类型
#include <typeinfo.h> int a = ; typeid(a).name(); 、lambda表达式用法
C++ 提供了对匿名函数的支持,称为 Lambda 函数(也叫 Lambda 表达式)。Lambda 表达式把函数看作对象。Lambda 表达式可以像对象一样使用,比如可以将它们赋给变量和作为参数传递,还可以像函数一样对其求值。Lambda 表达式本质上与函数声明非常类似。
[capture](parameters)->return-type{body} //例如
[](int x, int y) -> int { int z = x + y; return z + x; } int main(){
int a = ;
int b = ; auto lambda = []{return a + b;};
//error! 空捕获列表,无法使用作用域内其他变量 auto lambda = [](int a, int b){return a + b;};
//success auto lambda = [=]{return a + b;};
//success, 值传递 auto lambda = [=]{a++; b++; return a + b;};
//error! 值传递无法修改变量值 auto lambda = [&]{a++; b++; return a + b;};
//success, 引用传递 auto lambda = [&a, b]{a++; b++; return a + b;};
//error, 变量a引用传递,变量b值传递,故b不可修改 }

C++ 使用lambda表达式作为函数参数

模板参数
#include <iostream>
#include <string> template <typename F>
void print(F const &f){
std::cout<<f()<<std::endl;
} int main() {
std::cout << "Hello, World!" << std::endl; int num = ;
auto a = [&]//以引用的方式捕获本函数中的变量
() //无参数
->std::string {//返回值的类型为std::string
return std::to_string(num);
};
print(a);
num++;
print(a); return ;
}
调用print时,C++编译器会自动推断F的类型。运行上述程序,得到如下输出 Hello, World! 编译器需要支持c++11标准,有的编译器可能需要添加参数-std=c++。 使用std::function
#include <iostream>
#include <functional>
#include <string> void print(std::function<std::string ()> const &f){
std::cout<<f()<<std::endl;
} int main() {
std::cout << "Hello, World!" << std::endl; int num = ;
auto a = [&]//以引用的方式捕获本函数中的变量
() //无参数
->std::string {//返回值的类型为std::string
return std::to_string(num);
};
print(a);
num++;
print(a); return ;
}
stdL::function是个模板类;模板参数:返回值类型+函数参数类型列表;例如std::function<int  (int, int)> f,f可以指向任意一个返回指为int,参数为两个int类型的函数。 观察上面的程序,lambda表达式无参数,返回值类型为string;故在print函数中声明一个类型为function<std::string ()>类型的变量f,就可以用来接收a。注意:f前面必须加上const,否则编译过不了。至于加不加&,需要视程序而定,一般加上。

C++11 lambda表达式使用场景解析

Lambda表达式的使用场景

其实我在刚开始使用lambda的时候就挺好奇什么时候使用好,经常在不需要使用的时候使用上了,真的是多此一举,那么要在什么情况下使用呢?
因为lambda表达式又叫匿名函数(当然我们也可以理解为是一个未命名的内联函数),那么肯定就跟函数挂上关系了,通常情况写你在编程的时候需要将这段代码封装到一个函数里面再来调用,那这个时候就避免不了想函数名了,其实有时候取名字真的是件麻烦事,有时脑子突然短路都不知道命什么名字好了,那么这个时候你就要想起我们的lambda表达式了,它可以很好的帮你解决命名困难症这个问题。
那么还有什么情况下可以去考虑使用lambda表达式呢?在你的整个项目编程中,你独立出来一个函数,但这个函数实现相对简单并且可能在整个项目只使用了一次(即不存在复用的情况),那么这个时候我们就可以考虑使用下lambda表达式了,这样可以让代码更加紧凑,更加容易维护。

详解 C++11 lambda表达式的更多相关文章

  1. C# Lambda表达式详解,及Lambda表达式树的创建

    最近由于项目需要,刚刚学完了Action委托和Func<T>委托,发现学完了委托就必须学习lambda表达式,委托和Lambda表达式联合起来,才能充分的体现委托的便利.才能使代码更加简介 ...

  2. C++11 lambda 表达式

    C++11 新增了很多特性,lambda 表达式是其中之一,如果你想了解的 C++11 完整特性,建议去这里,这里,这里,还有这里看看.本文作为 5 月的最后一篇博客,将介绍 C++11 的 lamb ...

  3. C++11 lambda 表达式解析

    C++11 新增了很多特性,lambda 表达式是其中之一,如果你想了解的 C++11 完整特性,建议去这里,这里,这里,还有这里看看.本文作为 5 月的最后一篇博客,将介绍 C++11 的 lamb ...

  4. C++11 lambda表达式学习

    lambda表达式是函数式编程的基础.咱对于函数式编程也没有足够的理解,因此这里不敢胡言乱语,有兴趣的可以自己查找相关资料看下.这里只是介绍C++11中的lambda表达式自己的认识.这里有参考文档h ...

  5. C++ 11 Lambda表达式

    C++11的一大亮点就是引入了Lambda表达式.利用Lambda表达式,可以方便的定义和创建匿名函数.对于C++这门语言来说来说,“Lambda表达式”或“匿名函数”这些概念听起来好像很深奥,但很多 ...

  6. C++11 lambda表达式是如何实现的?

    lambda表达式是如何实现的呢? 其实是编译器为我们了创建了一个类,这个类重载了(),让我们可以像调用函数一样使用.所以,你写的lambda表达式和真正的实现,是这个样子的: 而对于捕获变量的lam ...

  7. C++ 11 Lambda表达式、auto、function、bind、final、override

    接触了cocos2dx 3.0,就必须得看C++ 11了.有分享过帖子:[转帖]漫话C++0x(四) —- function, bind和lambda.其实最后的Lambda没太怎么看懂. 看不懂没关 ...

  8. c++11——lambda表达式

    lambda表达式 函数式编程的一个语法,有如下优点: (1)声明式编程风格:就地匿名定义目标函数或函数对象,不需要额外写一个命名函数或者函数对象.以更直接的方式写程序,好的可读性和可维护性. (2) ...

  9. C++11 Lambda表达式简单解析

    C++11 新增了非常多特性,lambda 表达式是当中之中的一个.假设你想了解的 C++11 完整特性, 建议去http://www.open-std.org/看看新标准! 非常多语言都提供了 la ...

随机推荐

  1. MongoDB与Python的交互

    驱动模块 pymongo是python里常用的操作MongoDB的驱动模块 可用pip下载安装 pip install pymongo 创建连接 MongoClient是MongoDB的客户端代理对象 ...

  2. 使用Navicat Premium 12导出SQL语句并在Power Designer 16.5中生成物理模型

    内容简介 本文主要介绍使用Navicat Premium 12导出建表SQL(使用MySQL数据库)文件,并在Power Designer 16.5中使用导出的SQL文件来生成物理模型的步骤. 操作步 ...

  3. TPC-H 测试参考

    https://github.com/digoal/pg_tpch  ---明天以此为准 https://www.jianshu.com/p/83e670cf3ffb https://yq.aliyu ...

  4. QSetting介绍

    简介 QSettings类提供了持久的跨平台应用程序设置. 用户通常期望应用程序记住它的设置(窗口大小.位置等)所有会话.这些信息通常存储在Windows系统注册表,OS X和iOS的属性列表文件中. ...

  5. Linux下的Memcache安装 和 安装Memcache的PHP扩展

    一.首先安装服务端memcached 1.下载libevent与memcache软件包. 下载memcached: wget http://memcached.org/latestwget http: ...

  6. Kafka 深入核心参数配置

    Kafka 真是一个异常稳定的组件,服务器上我们部署了 kafka_2.11-1.0.1 版本的 kafka 除了几次计算时间太长触发了 rebalance 以外,基本没有处理过什么奇怪的问题. 但是 ...

  7. PHP查询oracle数据显示乱码问题

    1.Linux下 执行前脚本前先执行一下命令export NLS_LANG="SIMPLIFIED CHINESE_CHINA.AL32UTF8" 2.Windows下在代码里添加 ...

  8. Iptables 之二扩展模块 nat

    问题一:如果开发被动模式的ftp服务? 21号端口是命令连接端口,数据连接端口不固定 三步骤: (1)装载ftp追踪时的专用的模块 /lib/modules/$(uname-r)/kernel/ker ...

  9. Educational Codeforces Round 67 (Rated for Div. 2)

    A 考虑之前选中没有一个的,那么结果就是\(min(n-s,n-t)\) 那么能选中的第一次就是这个结果\(+1\),但需要拥有两个 \((s>t)\)考虑一开始选不中\(t\),则但选中\(t ...

  10. python3.x中lambda表达式的处理与python2不一样

    lambda表达式,在python2中的表达式和python3不同,原来只要: >>> map(lambda x: x ** 2, [1, 2, 3, 4, 5])          ...