lambda


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;
	// 简单范例1
	auto 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可以形成内联

	// 参数列表2
	auto 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;

	//返回类型4
	auto 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值