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. 第九周博客作业<西北师范大学|李晓婷>

    1.助教博客链接:https://home.cnblogs.com/u/lxt-/ 2.作业要求博客链接:https://www.cnblogs.com/nwnu-daizh/p/10726884.h ...

  2. thinkphp5 去除缓存

    array_map('unlink', glob(TEMP_PATH . '/*.php')); rmdir(TEMP_PATH);

  3. python timeit模块用法

    想测试一行代码的运行时间,在python中比较方便,可以直接使用timeit: >>> import timeit #执行命令 >>> t2 = timeit.Ti ...

  4. 常见的数据扩充(data augmentation)方法

    G~L~M~R~S 一.data augmentation 常见的数据扩充(data augmentation)方法:文中图片均来自吴恩达教授的deeplearning.ai课程 1.Mirrorin ...

  5. 0. Java虚拟机系列备忘预览图

    打算把Java虚拟机这块单独弄一个主题出来,做做备忘,结构如图所示: 后面还有一部分待更新...

  6. SOA 和 微服务

    正在读 钟华 著的<<企业IT架构转型之道 - 阿里巴巴中台战略思想与架构实战>> 一书, 参考了网上的讨论,  对SOA和微服务有了一些新的认识. 知乎上的讨论: SOA 与 ...

  7. JS 获取图片的base64编码

    获取图片的base64编码 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...

  8. 虚拟机有QQ消息时宿主机自动弹窗提示

    因为是检测窗口实现的,所以要求设置会话窗口自动弹出,而且看完消息就把QQ消息窗口关掉... 虚拟机端 #! /usr/bin/env python # -*- coding: utf-8 -*- fr ...

  9. This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its de 错误解决办法

    这是我们开启了bin-log, 我们就必须指定我们的函数是否是1 DETERMINISTIC 不确定的2 NO SQL 没有SQl语句,当然也不会修改数据3 READS SQL DATA 只是读取数据 ...

  10. MySQL数据库 Too many connections

    出现这种错误明显就是 mysql_connect 之后忘记 mysql_close:当大量的connect之后,就会出现Too many connections的错误,mysql默认的连接为100个, ...