做者:李春港
出处:http://www.javashuo.com/article/p-otyliogr-nx.htmlhtml
因为前段时间在阅读一些C++源码的时候发现了Lambda表达式,因此在此也记录下Lambda表达式的使用。ios
很早以前Lambda在不少高级语言中,就已经被普遍地使用了,在一个程序中Lambda表达式能够理解为是匿名函数。在C++中,到了C++11标准才引入了这个Lambda表达式,这是C++11最重要并且也是最经常使用的特性之一。express
使用Lambda表达式,不须要额外地定义函数名,能够更直接编写程序,有比较好的可读性和可维护性;不须要另外声明和定义函数体,避免了程序代码的膨胀。函数
[capture list] (params list) mutable exception-> return type { function body }
说明:this
名称 | 解析 |
---|---|
[capture list] | 捕获列表:lambda 表达式能够经过捕获列表捕获必定范围内的变量。 |
(params list) | 形参列表,用于传参(能够省略)。 |
mutable | 用来讲明是否能够修改按值捕获的变量(能够省略),若是须要修改按值捕获的变量,则须要添加。 |
exception | 异常设定(能够省略)。 |
return type | 返回类型 (可省略,若是省略则自动从函数体中判断返回类型,return后的值。若是没有则返回void)。 |
function body | 函数体,即逻辑代码。 |
编号 | 格式 | 特性 |
---|---|---|
格式1 | [capture list] (params list) -> return type {function body} | 一、没法修改捕获列表中的变量值。 |
格式2 | [capture list] (params list) {function body} | 一、没法修改捕获列表中的变量值;二、返回类型由return返回的值类型肯定,若是没有return语句,则返回类型为void。 |
格式3 | [capture list] {function body} | 一、没法修改捕获列表中的变量值;二、返回类型由return返回的值类型肯定,若是没有return语句,则返回类型为void;三、不能传入参数,相似普通的无参函数。 |
捕获形式 | 解析 |
---|---|
[ ] | 不捕获任何变量。 |
[&] | 捕获外部做用域中全部变量,并做为引用在函数体中使用(按引用捕获)。 |
[=] | 捕获外部做用域中全部变量,并做为副本在函数体中使用(按值捕获)。 |
[=,&x] | 按值捕获外部做用域中全部变量,并按引用捕获 x 变量。 |
[x] | 按值捕获 x 变量,同时不捕获其余变量。 |
[this] | 捕获当前类中的 this 指针,让 lambda 表达式拥有和当前类成员函数一样的访问权限。若是已经使用了 & 或者 =,就默认添加此选项。 |
注意:spa
/***************************************************************************** ** Copyright © 2020 lcg. All rights reserved. ** File name: Lambda.cpp ** Description: 在STL的sort函数参数使用Lambda表达式 ** Author: lcg ** Version: 1.0 ** Date: 2020.12.04 *****************************************************************************/ #include <iostream> #include <vector> #include <algorithm> using namespace std; bool cmp(int a, int b) { return a < b; } int main() { vector<int> vec{ 3, 2, 5, 7, 3, 2 }; vector<int> lbvec(vec); /**一、不使用Lambda表达式的写法**/ sort(vec.begin(), vec.end(), cmp); cout << "predicate function:" << endl; for (int it : vec) // 此for循环写法也是在C++11才出现 cout << it << ' '; cout << endl; /**二、使用Lambda表达式的写法**/ sort(lbvec.begin(), lbvec.end(), [](int a, int b) -> bool { return a < b; }); cout << "lambda expression:" << endl; for (int it : lbvec) cout << it << ' '; }
能够看到这种状况使用Lambda表达式能够使代码更加直观、简介,无需再定义 cmp(int a, int b) 函数。指针
/** 一、标明返回类型**/ auto f = [](int a) -> int { return a + 1; }; std::cout << f(1) << std::endl; /**输出: 2**/ /** 二、无标明返回类型**/ auto f = [](int a) { return a + 1; }; std::cout << f(1) << std::endl; /**输出: 2**/
当没有标明返回类型的时候,系统会根据return回来的值来判断返回值的类型,auto会自动检索返回值的类型。code
auto f = []() { return 1; }; std::cout << f() << std::endl; /**输出: 1**/
/***************************************************************************** ** Copyright © 2020 lcg. All rights reserved. ** File name: Lambda.cpp ** Description: 捕获外部变量的Lambda表达式 ** Author: lcg ** Version: 1.0 ** Date: 2020.12.04 *****************************************************************************/ #include <iostream> class A { public: int i_ = 0; void func(int x, int y) { /* error,没有捕获外部变量*/ auto x1 = []{ return i_; }; /*OK,按值捕获全部外部变量,包括了this指针*/ auto x2 = [=]{ return i_ + x + y; }; /*OK,按引用捕获全部外部变量,包括了this指针*/ auto x3 = [&]{ return i_ + x + y; }; /*OK,捕获this指针,Lambda拥有和此类中普通函数同样的权限*/ auto x4 = [this]{ return i_; }; /*error,没有捕获x、y,由于x、y变量不属于this*/ auto x5 = [this]{ return i_ + x + y; }; /* OK,捕获this指针、x、y*/ auto x6 = [this, x, y]{ return i_ + x + y; }; /*OK,捕获this指针,并修改为员的值*/ auto x7 = [this]{ return i_=7; }; x7(); std::cout<<i_<<std::endl;//输出7 /*OK,捕获全部外部变量,默认捕获this指针,并修改为员的值*/ auto x8 = [=]{ return i_=8; }; x8(); std::cout<<i_<<std::endl;//输出8 /*error,由于i_不属于捕获范围的变量,因此没法按值捕获i_变量,能够经过捕获this指针来获取i_使用权*/ auto x9 = [i_]{ return i_++; }; /*error,缘由同上*/ auto x10 = [&i_]{ return i_++; }; /*ok,按引用捕获全部变量,默认捕获this指针,并修改为员的值*/ auto x11 = [&]{ return i_=11; }; x11(); std::cout<<i_<<std::endl;//输出11 /*error,按值捕获x变量,并修改值*/ auto x12 = [x]{ return x++; }; /*ok,按值捕获x变量,并修改值*/ auto x13 = [x]()mutable{ return x=13; }; x13(); std::cout<<x<<std::endl;//输出1 /*ok,按引用捕获x变量,并修改值*/ auto x14 = [&x]{ return x=14; }; x14(); std::cout<<x<<std::endl;//输出14 } }; int main(int argc, char *argv[]) { A l; l.func(1,2); int a = 0, b = 1; /*error,没有捕获外部变量*/ auto f1 = []{ return a; }; /*OK,捕获全部外部变量,改变a值*/ auto f2 = [&]{ return a=2; }; f2(); std::cout<<a<<std::endl;//输出2 /*OK,捕获全部外部变量,并返回a*/ auto f3 = [=]{ return a; }; /*error,a是以复制方式捕获的,没法修改*/ auto f4 = [=]{ return a=4; }; /*ok,a是以复制方式捕获的,修改a值*/ auto f4 = [=]()mutable{ return a=4; }; f4(); std::cout<<a<<std::endl;//输出2 /*error,没有捕获变量b*/ auto f5 = [a]{ return a + b; }; /*OK,捕获a和b的引用,并对b作自加运算*/ auto f6 = [a, &b]{ return a + (b++); }; /*OK,捕获全部外部变量和b的引用,并对b作自加运算*/ auto f7 = [=, &b]{ return a + (b++); }; return 0; }
总结:htm