c++11——lambda表达式
2015-09-12 17:33
369 查看
lambda表达式
函数式编程的一个语法,有如下优点:(1)声明式编程风格:就地匿名定义目标函数或函数对象,不需要额外写一个命名函数或者函数对象。以更直接的方式写程序,好的可读性和可维护性。
(2)简洁:不需要额外再写一个函数或者函数对象,避免了代码膨胀和功能分散。
(3)在需要的时间和地点实现功能闭包,使程序更灵活。
lambda表达式基本概念和用法
lambda表达式定义了一个匿名函数,并且可以捕获一定范围的变量。lambda表达式的语法如下:[capture] (params) opt -> ret {body;}
其中,capture为捕获列表;params是参数表;opt为函数选项;ret为返回值类型;body是函数体。捕获列表是将lambda外部的一些变量引入lambda内部,可以为值类型或引用类型。
auto f = [] (int a) -> int {return a + 1;}; std::cout << f(1) << std::endl;
或者省略返回值类型(c++11可以进行类型推导),直接写成
auto f = [](int a){return a+1;}; std::cout << f(1) << std::endl;
[b]捕获列表[/b]
lambda表达式可以通过捕获列表捕获一定范围内的变量:
[] 不捕获任何变量
[&] 捕获外部作用域中的所有变量,并作为引用在函数体内使用(按引用捕获)
[=] 捕获外部作用域内的所有变量,并作为副本在函数体内使用(按值捕获)
[=, &foo] 按值捕获外部作用域中的所有变量,并按引用捕获foo变量
[bar] 按值捕获bar变量,同时不捕获其他变量
[this] 捕获当前类中的this指针,让lambda表达式拥有和当前类成员函数同样的访问权限。如果已经使用了=或者&,就默认添加此项。捕获this的目的是可以在lambda中使用当前类的成员函数和成员变量。
int a = 0, b = 1; auto f1 = []{return a;} ;//错误,没有捕获外部变量 auto f2 = [&]{return a++;};//捕获外部变量的引用,并且可以实现将a++ auto f3 = [=]{return a;}; auto f4 = [=]{return a++;};//错误,a是一个副本,并且为const类型,无法修改 auto f5 = [a, &b]{return a + (b++);}//可以,按值捕获a,并且按引用捕获b
需要注意,默认情况下,lambda表达式无法修改通过复制方式捕获的外部变量。如果希望修改这些外部变量,可以通过引用方式进行捕获,或者通过显式指明lambda表达式为mutable类型:
int a = 0; auto f1 = [=]{return a++;};//错误 auto f2 = [=]()mutable{return a++;} //需要注意,mutable修饰的lambda即使没有参数,也要书写参数列表 int main(){ int a = 1; auto f = [=]{return a+1; }; cout << f() << endl; //输出2 cout << "a = " << a << endl; //a = 1 auto f1 = [=]()mutable{return a++; }; cout << "a = " << a << endl; //a = 1 cout << f() << endl; //输出2 ???? cout << "a = " << a << endl; //a = 1 return 0; }
以及需要注意lambda的延迟调用
int a = 0;
auto f = [=]{return a;};
a += 1;
std::cout << f() << std::endl; //输出的a为之前的a
lambda表达式按值捕获外部的变量,在捕获的一瞬间,这些值就被复制到f中。
[b]lambda表达式和闭包[/b]
在c++11中,lambda为闭包类型,是一个特殊的、匿名的非union的类类型。可以认为lambda是一个带有operator()的类,即仿函数。因此可以使用std::function和std::bind来存储和操作lambda表达式。
std::function<int(int)> f1 = [] (int a){return a;}; std::function<int(void)> f2 = std::bind([](int a){return a;}, 123);
对于没有捕获任何变量的lambda表达式,还可以被转换成一个普通的函数指针:
using func_t = int(*)(int); func_t f = [](int a){return a;}; f(123);
可以认为lambda是一个带有operator()的类,即仿函数。按照c++的标准,lambda表达式的operator()默认是const的,因此在按值捕获的时候不能修改外部变量的值;而使用mutable可以取消 operator()的const。
就地声明和使用lambda表达式
int count = count_if(coll.begin(), coll.end(), [](int x){return x > 5 && x < 10;});
+
相关文章推荐
- C++字符数组的输入输出和字符串结束标志使用讲解
- C语言:二叉树的相关操作
- C++ explicit的用法
- 深入解析C++中的字符数组和处理字符串的方法
- 「C语言回 4000 顾之旅」第一篇:指针详解
- 「C语言回顾之旅」第一篇:指针详解
- C++中智能指针的设计和使用
- Windows下Setting Up a Project(建立一个工程)
- 哈希表实现电话号码查询系统(c++)
- [C++]函数调用栈
- c++11——std::function和bind绑定器
- 趣味C语言(1)---绘制余弦曲线
- C++虚析构函数、纯虚析构函数
- c++ 玩转 vector容器 用法
- C++学习笔记 -- 虚析构函数与纯虚析构函数
- C++ 虚函数&纯虚函数&抽象类&接口&虚基类
- c++函数返回值的引用
- 详解C++中的一维数组和二维数组
- C语言中的内存分布
- 隔一个月生兔子的C语言实现