C++11 带来的新特性 (4)—— 匿名函数(Lambdas)
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)的更多相关文章
- C++11 带来的新特性 (3)—— 关键字noexcept
1 关键字noexcept 从C++11开始,我们能看到很多代码当中都有关键字noexcept.比如下面就是std::initializer_list的默认构造函数,其中使用了noexcept. co ...
- C++11 带来的新特性 (2)—— 统一初始化(Uniform Initialization)
1 统一初始化(Uniform Initialization) 在C++ 11之前,所有对象的初始化方式是不同的,经常让写代码的我们感到困惑.C++ 11努力创造一个统一的初始化方式. 其语法是使用{ ...
- C++11 带来的新特性 (1)
1 语法改进 1.1 模板表达式中的空格 在c++03 及以前 vector<list<int>>; //Error vector<list<int> > ...
- (数据科学学习手札139)geopandas 0.11版本重要新特性一览
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 大家好我是费老师,就在几天前,geopandas ...
- C++11新特性:Lambda函数(匿名函数)
声明:本文参考了Alex Allain的文章http://www.cprogramming.com/c++11/c++11-lambda-closures.html 加入了自己的理解,不是简单的翻译 ...
- Mysql8.0.11简介,新特性
MySQL 8.0 正式版 8.0.11 已发布,官方表示 MySQL 8 要比 MySQL 5.7 快 2 倍,还带来了大量的改进和更快的性能! 注意:从 MySQL 5.7 升级到 MySQL 8 ...
- 发布倒计时!JDK11为我们带来哪些新特性?
今年7月底,JDK11已经进入了Rampdown Phase Two阶段,这标志着该版本所有特性已经被冻结,不会有新的JEP会加入版本中. 这一阶段将会修复P1–P2级BUG,之后,JDK11预定于今 ...
- Git 2.7: 一个新的带来许多新特性和性能提升的主要版本
在2.6版本发布两个月之后,Git 2.7发布.该版本带来了许多新特性以及性能的提升. 本文选取了Git 2.7带来的主要变化: git remote支持get-url子命令,可以显示指定远端的URL ...
- kafka 幂等生产者及事务(kafka0.11之后版本新特性)
1. 幂等性设计1.1 引入目的生产者重复生产消息.生产者进行retry会产生重试时,会重复产生消息.有了幂等性之后,在进行retry重试时,只会生成一个消息. 1.2 幂等性实现1.2.1 PID ...
随机推荐
- 第九周博客作业<西北师范大学|李晓婷>
1.助教博客链接:https://home.cnblogs.com/u/lxt-/ 2.作业要求博客链接:https://www.cnblogs.com/nwnu-daizh/p/10726884.h ...
- thinkphp5 去除缓存
array_map('unlink', glob(TEMP_PATH . '/*.php')); rmdir(TEMP_PATH);
- python timeit模块用法
想测试一行代码的运行时间,在python中比较方便,可以直接使用timeit: >>> import timeit #执行命令 >>> t2 = timeit.Ti ...
- 常见的数据扩充(data augmentation)方法
G~L~M~R~S 一.data augmentation 常见的数据扩充(data augmentation)方法:文中图片均来自吴恩达教授的deeplearning.ai课程 1.Mirrorin ...
- 0. Java虚拟机系列备忘预览图
打算把Java虚拟机这块单独弄一个主题出来,做做备忘,结构如图所示: 后面还有一部分待更新...
- SOA 和 微服务
正在读 钟华 著的<<企业IT架构转型之道 - 阿里巴巴中台战略思想与架构实战>> 一书, 参考了网上的讨论, 对SOA和微服务有了一些新的认识. 知乎上的讨论: SOA 与 ...
- JS 获取图片的base64编码
获取图片的base64编码 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> ...
- 虚拟机有QQ消息时宿主机自动弹窗提示
因为是检测窗口实现的,所以要求设置会话窗口自动弹出,而且看完消息就把QQ消息窗口关掉... 虚拟机端 #! /usr/bin/env python # -*- coding: utf-8 -*- fr ...
- 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 只是读取数据 ...
- MySQL数据库 Too many connections
出现这种错误明显就是 mysql_connect 之后忘记 mysql_close:当大量的connect之后,就会出现Too many connections的错误,mysql默认的连接为100个, ...