介绍Lambad表达式
C++11中引入了Lambda表达式 用于定义并创建匿名函数对象,以简化编程工作。
首先我们了解一下Lambda表达式的格式:
[函数对象参数](操作符重载函数参数)mutable->返回值类型{函数体}
1. [capture](parameters)mutable->return-type 2. { 3. statement; 4. }
1.函数对象参数(也叫捕获列表):[]标识一个Lambda的开始,不可省略。函数对象参数是传递给编译器自动生成的函数对象类的构造函数的。函数对象参数只能使用那些定义Lambda为止时且在Lambda所在作用范围内可见的局部变量和所在类的this。函数对象参数有下面几种:
1.[] 空的,就是无法访问作用域外的。
- [=] 等号运算符。表示函数体内可以使用Lambda所在作用范围内且所有可见的局部变量和所在类的this,而且是值传递方式。
- [&] 取地址运算符。表示函数体内可以使用Lambda所在作用范围内且所有可见的局部变量和所在类的this,而且是引用传递方式。
- this。函数体内可以使用Lambda所在类中的成员变量。
- a。将a按值进行传递。按值传递时,函数体内不能修改传递进来变量的值,因为默认情况下函数是const的。要修改传递进来的值,需要添加mutable关键字。
- &a。将a按照引用传递。
2.操作符重载函数参数:表示重载的()操作符的参数,没有参数时,这部分可以省略。参数可以按值和按引用俩种方式进行传参。
3.可修改标识符:mutable声明,这部分可以省略。按值传递时,加上mutable修饰符后就可以修改传进来的拷贝变量。
4.函数返回值:->返回值类型。表示函数返回值类型,当返回值为void,或者函数体中只有一处return的地址时,这部分可以省略。因为只有一处return时编译器可以自动推测出返回值类型。
5.函数体:{} 函数实现的位置。这部分不可省略。当函数体可以为空。
用例说明
值传递
最后加个()就是函数调用。不加的话只是个函数声明。
int main() { // 最后加个()就是函数调用 [=](int i) { cout << "LinXi" << i << endl; }(3); return 0; }
int main() { // 最后加个()就是函数调用 int x = 23; [x]() { cout << "LinXi" << x << endl; }(); cout << x << endl; return 0; }
当我尝试修改值传递进去的值时就会报错。
引用传递(可读可写)
函数里面修改,外部的x值就会改变。
int main() { // 最后加个()就是函数调用 int x = 23; [&](int& i) { cout << "LinXi" << ++i << endl; }(x); cout << x << endl; return 0; }
int main() { // 最后加个()就是函数调用 int x = 23; [&x]() { cout << "LinXi" << ++x << endl; }(); cout << x << endl; return 0; }
运行结果图:
mutable关键字
int main() { // 最后加个()就是函数调用 int x = 23; [x]()mutable { cout << "LinXi" << ++x << endl; }(); cout << x << endl; return 0; }
可以看到在函数内部对x的值进行了修改 ,但是外面x的值依然没变。
有返回值
int main() { // 最后加个()就是函数调用 const int ret = []()->int { return 1024; }(); cout << ret << endl; return 0; }
实战小例子
使用lambda表达式遍历数据
template<class T, class T2> void For_each(const T* arr, int cnt, T2 t2) { for (auto i = 0; i < cnt; ++i) { t2(arr[i]); } } int main() { int arr[] = { 9,6,5,2,3,1,4,7 }; int*p = arr; For_each(p, sizeof(arr) / sizeof(arr[0]), [&](const int& num) { cout << num << " "; }); cout << endl; return 0; }
使用仿函数求数组的和
struct Sum //仿函数 { private: int total = 0; public: void operator()(int val) { total += val; } void output() const { cout << "total = " << total << endl; } }; template<class T, class T2> T2 For_each(const T* arr, int cnt, T2 t2) { for (int i = 0; i < cnt; ++i) { t2(arr[i]); } return t2; } int main() { int arr[] = { 6,5,3,2,1,9,8,74 }; Sum sum = For_each(arr, 8, Sum()); sum.output(); return 0; }