lambda

来源:互联网 发布:ac68u 广电网络 编辑:程序博客网 时间:2024/05/16 04:52


Capture 子句
Lambda 可在其主体中引入新的变量(用 C++14),它还可以访问(或“捕获”)周边范围内的变量。
1.[var]表示值传递方式捕捉变量var

2.[=]表示值传递方式捕捉所有父作用域的变量(包括this)

3.[&var]表示引用传递捕捉变量var;

4.[&]表示引用传递方式捕捉所有父作用域的变量(包括this);

5.[this]表示值传递方式捕捉当前的this指针。

空 capture 子句 [ ] 指示 lambda 表达式的主体不访问封闭范围中的变量。
可以使用默认捕获模式(标准语法中的 capture-default)来指示如何捕获 lambda 中引用的任何外部变量(使用 capture-default 时,只有 lambda 中提及的变量才会被捕获)

注意事项:
引用捕获可用于修改外部变量,而值捕获却不能实现此操作。 (mutable允许修改副本,而不能修改原始项。) 
引用捕获会反映外部变量的更新,而值捕获却不会反映。 
引用捕获引入生存期依赖项,而值捕获却没有生存期依赖项。 当 lambda 以异步方式运行时,这一点尤其重要。 如果在异步 lambda 中通过引用捕获本地变量,该本地变量将很可能在 lambda 运行时消失,从而导致运行时访问冲突。

 
参数列表
在 C++14 中,如果参数类型是泛型,则可以使用 auto 关键字作为类型说明符。 这将告知编译器将函数调用运算符创建为模板。 参数列表中的每个 auto 实例等效于一个不同的类型参数。 


可变规范
通常,lambda 的函数调用运算符为 const-by-value,但对 mutable 关键字的使用可将其取消。 它不会生成可变的数据成员。 利用可变规范,lambda 表达式的主体可以修改通过值捕获的变量

返回类型
将自动推导 lambda 表达式的返回类型。 无需使用 auto 关键字,除非指定尾随返回类型。 trailing-return-type 类似于普通方法或函数的返回类型部分。 但是,返回类型必须跟在参数列表的后面,你必须在返回类型前面包含 trailing-return-type 关键字 ->。 
如果 lambda 体仅包含一个返回语句或其表达式不返回值,则可以省略 lambda 表达式的返回类型部分。 如果 lambda 体包含单个返回语句,编译器将从返回表达式的类型推导返回类型。 否则,编译器会将返回类型推导为 void

Lambda 体
从封闭范围捕获变量,如前所述。 
参数 
本地声明变量 
类数据成员(在类内部声明并且捕获 this 时) 
具有静态存储持续时间的任何变量(例如,全局变量) 

// ex10181242.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include<iostream>#include<string>#include <algorithm>#include <cmath>using namespace std;void abssort(float* x, unsigned n) {std::sort(x, x + n,// Lambda expression begins[](float a, float b) {return (std::abs(a) < std::abs(b));} // end of lambda expression);}int add(int a, int b)//error C3533: 参数不能为包含“auto”的类型{return a + b;}void foo(){//}int g_i = 1000;int main(){int a = 1,b= 2;// 简单范例1auto funAdd = [=](int a,int b)->int //优点1(距离):不用提前声明,让定义位于使用的地方附近, 这样无需翻阅多面源代码,函数的缺点是不能在其他函数内定义{return a + b;};cout << "funAdd(a,b)  = " << funAdd(a, b) << endl;//捕获范例1 auto refLambda = [&]() { a++; };//优点2(功能:捕获动态变量)以引用的形式捕获任何外部变量引用 也可以单独捕获变量a [&a]  refLambda();cout << "a = " << a << endl;//auto valLambda = [=]() { a++; };//错误,以值的形式传递,相当于一个常量值 ,不可以改变//valLambda(a);int c = 3;auto refvalLambda = [&a, b]() {a++; cout << "b = " << b << endl; /*cout << c << endl;*/ };//也可以组合,没有捕获的在表达式中不可用,但不能重复的捕获refvalLambda();cout << "a = " << a << endl;// 优点3(效率):用函数指针不可以形成内联,编译器不会其地址被获取的函数,因为函数地址的概念意味着非内联函数,但lambda可以形成内联// 参数列表2auto foo = [](auto a, auto b) {return a + b; };// 函数中则不可以cout << "foo(1,1) = " << foo(1, 1) << endl;cout << "foo(1.2,1.3) = " << foo(1.2, 1.3) << endl;// 可变规范3 auto mutableValLambda = [=]()mutable {a++; };// 未加mutable 相当于一个常函数  这里的修改也只是一个副本而已cout << "before mutableValLambda a = " << a << endl;mutableValLambda();cout << "after mutableValLambda  a = " << a << endl;auto mutableRefLambda = [&]()mutable {a++; };cout << "before mutableRefLambda a = " << a << endl;mutableRefLambda();cout << "after mutableRefLambda  a = " << a << endl;//返回类型4auto x1 = [](int i) { return i; };cout << "x1(1) = " << x1(1) << endl;//auto x2 = [] { return{ 1, 2 }; }; wrong //lambda 体int m = 0;int n = 0;[&, n](int a) mutable { m = ++n + a; }(4);// 参数 本地声明变量 因此在调用 lambda 表达式后,变量的值仍保持 0 不变。 mutable  规范允许在 lambda 中修改 n。cout << m << endl << n << endl;// 5,0 static int s_i = 100;cout << "s_i = " << s_i << endl;[&]()mutable{s_i++; }();cout << "s_i = " << s_i << endl;cout << "g_i = " << g_i << endl;[&]()mutable {g_i++; }();cout << "g_i = " << g_i << endl;//在STL较多使用float farr[3] = { 3.2,4.1,-2.1 };abssort(farr, 3);for(auto f :farr) //c++ 11 序列for循环 遍历数组,容器,string以及由begin和end函数定义的序列(即有Iterator)cout << f << ' ';getchar();return 0;}





0 0
原创粉丝点击