1 语法

Lambdas并不是新概念,在其它语言中已经烂大街了。直接进入主题,先看语法:

[ captures ] ( params ) specifiers exception attr -> ret { body }    (1)
[ captures ] ( params ) -> ret { body } (2)
[ captures ] ( params ) { body } (3)
[ captures ] { body } (4)
  • captures:捕获参数。详细格式见下图。
格式 意义
[] 默认不捕获任何变量
[=] 默认以值捕获所有变量
[&] 默认以引用捕获所有变量
[x] 仅以值捕获x,其它变量不捕获
[&x] 仅以引用捕获x,其它变量不捕获
[=, &x] 默认以值捕获所有变量,但是x是例外,通过引用捕获
[&, x] 默认以引用捕获所有变量,但是x是例外,通过值捕获
[this] 通过引用捕获当前对象(其实是复制指针)
[*this] 通过传值方式捕获当前对象
  • params:参数列表。
  • ret:返回类型。
  • body:函数体。
  • specifiers:限定符列表。比如mutable。
  • exception:异常规定。比如noexcept。
  • attr:属性规定,详见。

2 使用

Lambdas重在使用,所以下面直接上实例,由浅入深的介绍使用方法。

2.1 打印字符串

  • 定义一个匿名函数
[]{
std::cout<< "hello world!" <<std::endl;
}
  • 调用匿名函数
[]{
std::cout<< "hello world!" <<std::endl;
}();
  • 传递匿名函数给一个变量
auto l = []{
std::cout<< "hello world!" <<std::endl;
};
l();

2.2 带参数列表的匿名函数

auto l = [](const std::string &s){
std::cout<< s <<std::endl;
};
l("hello world!");

2.3 指定返回值类型的匿名函数

[] -> double{
return 42;
}

等价于

[]{
return 42;
}

如果不指定返回类型,C++11也可以自动推断类型。

2.4 带捕获参数的匿名函数

  • 捕获变量值+捕获变量引用
int x = 0;
int y = 42;
auto f = [x, &y] {
std::cout<<"x:" << x << std::endl;
std::cout<<"y:" << y << std::endl;
++y;
//++x;//Error
};
x = y = 77;
f();
f();
std::cout<< "final y: " << y <<std::endl;

输出

x:0
y:77
x:0
y:78
final y: 79
  • 捕获所有变量值
int x = 0;
int y = 42;
auto f = [=] {
std::cout<<"x:" << x << std::endl;
std::cout<<"y:" << y << std::endl;
//++y;//Error
//++x;//Error
};
x = y = 77;
f();
f();
std::cout<< "final y: " << y <<std::endl;

输出

x:0
y:42
x:0
y:42
final y: 77
  • 捕获所有变量引用
int x = 0;
int y = 42;
auto f = [&] {
std::cout<<"x:" << x << std::endl;
std::cout<<"y:" << y << std::endl;
++y;//Error
++x;//Error
};
x = y = 77;
f();
f();
std::cout<< "final x: " << x <<std::endl;
std::cout<< "final y: " << y <<std::endl;

输出

x:77
y:77
x:78
y:78
final x: 79
final y: 79

2.5 使用匿名函数统计容器中所有元素的值之和

std::vector<int> vec = { 1, 2, 3, 4, 5 };
double total = 0; //inclucde 'algorithm' for foreach
std::foreach(begin(vec), end(vec),
[&](int x) {
total += x;
});
std::cout<<"total:"<< total <<std::endl;

输出:

total:15

2.6 使用匿名函数对容器中的元素排序

struct Point{
double x,y;
Point(){
x = (rand() % 10000) - 5000;
y = (rand() % 10000) - 5000;
} void Print(){
std::cout<<"["<<x<<","<<y<<"]"<<std::endl;
}
}; int count = 10;
std::vector<Point> points;
for( auto i = 0; i < 10 ; i++ ) points.push_back(Point()); cout<<"Unsorted:"<<endl;
for( auto i = 0; i < 10 ; i++ ) points[i].Print(); std::sort(points.begin(), points.end(),
[](const Point& a, const Point& b) -> bool{
return (a.x * a.x) + (a.y * a.y) < (b.x * b.x) + (b.y * b.y);
});
cout<<"Sorted:"<<endl;
for( auto i = 0; i < 10 ; i++ ) points[i].Print();

输出:

Unsorted:
[4383,-4114]
[-2223,1915]
[2793,3335]
[386,-4508]
[1649,-3579]
[-2638,-4973]
[3690,-4941]
[2763,-1074]
[-4460,-1574]
[4172,736]
Sorted:
[-2223,1915]
[2763,-1074]
[1649,-3579]
[4172,736]
[2793,3335]
[386,-4508]
[-4460,-1574]
[-2638,-4973]
[4383,-4114]
[3690,-4941]

2.7 返回匿名函数类型

//include<functional>
std::function<int(int,int)> returnLambda (){
return [](int x, int y){
return x*y;
};
} auto lf = returnLambda();
std::cout<< lf(6,7) << std::endl;

2.8 奇怪的捕获变量作用域

void PerformOperation( function<void()> f ){
f();
} int main(){
int x = 100;
auto func = [&](){ x++;};
PerformOperation(func);
std::cout<< "x:" << x << std::endl;
return 0;
}

输出:

x:101

C++11 带来的新特性 (4)—— 匿名函数(Lambdas)的更多相关文章

  1. C++11 带来的新特性 (3)—— 关键字noexcept

    1 关键字noexcept 从C++11开始,我们能看到很多代码当中都有关键字noexcept.比如下面就是std::initializer_list的默认构造函数,其中使用了noexcept. co ...

  2. C++11 带来的新特性 (2)—— 统一初始化(Uniform Initialization)

    1 统一初始化(Uniform Initialization) 在C++ 11之前,所有对象的初始化方式是不同的,经常让写代码的我们感到困惑.C++ 11努力创造一个统一的初始化方式. 其语法是使用{ ...

  3. C++11 带来的新特性 (1)

    1 语法改进 1.1 模板表达式中的空格 在c++03 及以前 vector<list<int>>; //Error vector<list<int> > ...

  4. (数据科学学习手札139)geopandas 0.11版本重要新特性一览

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 大家好我是费老师,就在几天前,geopandas ...

  5. C++11新特性:Lambda函数(匿名函数)

    声明:本文参考了Alex Allain的文章http://www.cprogramming.com/c++11/c++11-lambda-closures.html 加入了自己的理解,不是简单的翻译 ...

  6. Mysql8.0.11简介,新特性

    MySQL 8.0 正式版 8.0.11 已发布,官方表示 MySQL 8 要比 MySQL 5.7 快 2 倍,还带来了大量的改进和更快的性能! 注意:从 MySQL 5.7 升级到 MySQL 8 ...

  7. 发布倒计时!JDK11为我们带来哪些新特性?

    今年7月底,JDK11已经进入了Rampdown Phase Two阶段,这标志着该版本所有特性已经被冻结,不会有新的JEP会加入版本中. 这一阶段将会修复P1–P2级BUG,之后,JDK11预定于今 ...

  8. Git 2.7: 一个新的带来许多新特性和性能提升的主要版本

    在2.6版本发布两个月之后,Git 2.7发布.该版本带来了许多新特性以及性能的提升. 本文选取了Git 2.7带来的主要变化: git remote支持get-url子命令,可以显示指定远端的URL ...

  9. kafka 幂等生产者及事务(kafka0.11之后版本新特性)

    1. 幂等性设计1.1 引入目的生产者重复生产消息.生产者进行retry会产生重试时,会重复产生消息.有了幂等性之后,在进行retry重试时,只会生成一个消息. 1.2 幂等性实现1.2.1 PID ...

随机推荐

  1. Android Bundle详解

    http://blog.csdn.net/cswhale/article/details/39053411 1 Bundle介绍 Bundle主要用于传递数据:它保存的数据,是以key-value(键 ...

  2. leveldb实现原理

    LevelDb日知录之一:LevelDb 101 说起LevelDb也许您不清楚,但是如果作为IT工程师,不知道下面两位大神级别的工程师,那您的领导估计会Hold不住了:Jeff Dean和Sanja ...

  3. dpdk之路-环境部署

    dpdk实验环境部署 1.实验环境说明 vmware workstatioin 12 centos 7.5.1804 dpdk-stable-18.11.1 2.实验步骤 (1)虚拟机安装 http: ...

  4. AJAX原理解析与兼容方法封装

    AJAX常用参数 AJAX对象兼容 AJAX对象方法与属性 AJAX封装兼容方法源码 AJAX全称Asynchronous JavaScript and XML(异步的JavaScript与XML), ...

  5. 【游戏开发】基于VS2017的OpenGL开发环境搭建

    一.简介 最近,马三买了两本有关于“计算机图形学”的书籍,准备在工作之余鼓捣鼓捣图形学和OpenGL编程,提升自己的价值(奔着学完能涨一波工资去的).俗话说得好,“工欲善其事,必先利其器”.想学习图形 ...

  6. 2018-2019-2 实验二 Java面向对象程序设计

    实验内容 1.初步掌握单元测试和TDD 2.理解并掌握面向对象三要素:封装.继承.多态 3.初步掌握UML建模 4.熟悉S.O.L.I.D原则 5.了解设计模式 实验要求 1.没有Linux基础的同学 ...

  7. HBase基本概念与基本使用

    1. HBase简介 1.1 什么是HBase HBASE是一个高可靠性.高性能.面向列.可伸缩的分布式存储系统,利用HBASE技术可在廉价PC Server上搭建起大规模结构化存储集群. HBASE ...

  8. css/css3 未知元素宽高,垂直居中和水平居中

    未知元素的宽高情况下  垂直居中和水平居中 第一种 flex盒布局 (推荐) /*弹性盒模型*/ /*主轴居中对齐*/ /*侧轴居中对齐*/ .ele{ display:flex; justify-c ...

  9. 五十四、linux 编程——TCP 编程模型

    54.1 编程模型介绍 54.1.1 TCP 客户端服务器编程模型 客户端调用序列 调用 socket 函数创建套接字 调用 connect 连接服务器端 调用 I/O 函数(read/write) ...

  10. 关于接口(Interface)

    接口,其实是指类之间约定的协议,可以包含方法.属性.事件和索引: 接口成员不允许使用访问修饰符号(public.private.protected.internal),所有的接口成员都是公共的. 接口 ...