C++11 Lambda表达式

Lambda表达式简介
 

Lambda表达式是现代C++在C++11和更高版本中的一个新的语法糖。它是一种定义匿名函数对象的便捷方法,常用于封装传递给算法或异步方法的几行代码。Lambda表达式可以在调用或作为函数参数传递的位置处定义,可以捕获上下文中的变量供函数使用。Lambda表达式的语法定义包括捕获列表、参数列表、可变规格、异常说明、返回类型和函数体。捕获列表描述了Lambda函数可以访问的上下文变量及传递方式,参数列表类似于普通函数的参数列表,可变规格用于取消Lambda函数的常量性,异常说明用于指示Lambda函数是否会引发异常,返回类型可以省略让编译器推导,函数体可以包含任意内容。Lambda表达式的优点包括在需要调用函数的位置定义短小精悍的函数,代码紧凑且可读性高。缺点是语法相对灵活增加了阅读难度,对于函数复用有限。Lambda表达式的工作原理是编译器会把Lambda表达式生成一个匿名类的匿名对象,并在类中重载函数调用运算符,实现了一个operator()方法。这样可以用Lambda表达式构造一个函数对象。

 Lambda表达式在C++中的语法定义
 

在C语言中,没有直接支持Lambda表达式的语法。 Lambda表达式是C++11引入的新特性,它允许在函数调用或作为函数参数传递的位置定义匿名函数对象。C++的Lambda表达式的语法定义与函数定义相似,一般形式为:

[捕获列表](参数列表) mutable noexcept -> 返回类型 {函数体}

示例 1 :
 

int main()
{
	// 两个数相加的lambda
	auto add1 = [](int a, int b)->int{return a + b; };
	cout << add1(1, 2) << endl;

	// 省略返回值
	auto add2 = [](int a, int b){return a + b; };
	cout << add2(1, 2) << endl;

	
	return 0;
}

示例2

int main()
{
	// 交换变量的lambda
	int x = 0, y = 1;
	auto swap1 = [](int& x1, int& x2)->void {int tmp = x1; x1 = x2; x2 = tmp; };
	swap1(x, y);
	cout << x << ":" << y << endl;

	auto swap2 = [](int& x1, int& x2)
	{
		int tmp = x1;
		x1 = x2;
		x2 = tmp;
	};

	swap2(x, y);
	cout << x << ":" << y << endl;

	// 不传参数交换x y的lambda  -- 捕捉列表
	// 默认捕捉的对象不能修改
	/*auto swap3 = [x, y]()mutable
	{
		int tmp = x;
		x = y;
		y = tmp;
	};

	swap3();
	cout << x << ":" << y << endl;*/

	auto swap4 = [&x, &y]
	{
		int tmp = x;
		x = y;
		y = tmp;
	};

	swap4();
	cout << x << ":" << y << endl;
	return 0;
}

Lambda表达式注意以下几个问题:

一: Lambda表达式的捕获列表有哪些形式?
1. []:表示不捕获任何变量。

int main()
{
	int a = 9;
	[]() {cout << a << endl; };
	system("pause");
	return 0;
}


2. [var]:表示值传递方式捕获变量var。

int main()
{
	int a = 9;
	auto lam = [a]() {cout << a << endl; };
	lam();
	return 0;
}


3. [var, &]:表示值传递方式捕获变量var,并通过引用传递方式捕获其他所有变量。

#include <iostream>
using namespace std;
int main()
{
    int a = 9;
    int b = 5;
    int &x = b;
    x = 8;
    auto lam = [a, &]()
    {
        cout << a << " " <<x <<endl;
    };
    lam();
    return 0;
}


4. [=]:表示以值传递的方式捕获所有变量。

int main()
{
	int a = 9;
	string s = "hello";
	auto lam = [=]() {cout << a << " "<<s<<endl; };
	lam();
	return 0;
}


5. [&]:表示以引用传递的方式捕获所有变量。

int main()
{
	int a = 9;
	auto lam = [&a]() {a = 10; cout << a << endl; };
	lam();
	return 0;
}


6. [&, var]:表示以引用传递的方式捕获所有变量,并值传递方式捕获变量var。

int main()
{
	int a = 9;
	string s = "hello";
	auto lam = [&, a]() {s = "hhah"; cout << a << " " << s << endl; };
	lam();
	
	return 0;
}


7. [=, &var]:表示以值传递的方式捕获所有变量,并引用传递方式捕获变量var。

int main()
{
	int a = 9;
	string s = "hello";
	auto lam = [=, &a]() {a = 90; cout << a << " " << s << endl; };
	lam();
	
	return 0;
}

需要注意的是,捕获列表不允许变量重复传递,否则会导致编译时错误。
 

二:Lambda表达式的捕获范围

//捕捉列表的参数来源范围--当前栈帧 (注意全局变量)
int func()
{
	int a, b, c, d, e;
	a = b = c = d = e = 1;

	// 全部传值捕捉
	auto f1 = [=](){
		cout << a << b << c << d << e << endl;
	};

	f1();

	// 混合捕捉
	auto f2 = [=, &a](){
		a++;
		cout << a << b << c << d << e << endl;
	};

	f2();
	static int x = 0;

	if (a)
	{
		auto f3 = [&, a](){
			//a++;//error
			b++;
			c++;
			d++;
			e++;
			val++;
			x++;
			cout << a << b << c << d << e << endl;
		};

		f3();
	}


	return 0;
}

int main()
{
	//error
	//auto f4 = [&, a](){
	//	//a++;
	//	b++;
	//	c++;
	//	d++;
	//	e++;
	//	f++;
	//	cout << a << b << c << d << e << endl;
	//};

	//f4();

	return 0;
}

三: Lambda表达式可以接受哪些参数?

 Lambda表达式可以接受不同类型的参数,具体取决于功能接口中声明的方法的参数类型。参数可以是基本类型、对象类型、函数式接口类型或泛型类型。Lambda表达式的参数列表可以为空,也可以有一个或多个参数。参数列表需要用圆括号括起来,多个参数之间用逗号分隔。当只有一个参数时,可以省略圆括号。Lambda表达式的参数可以在箭头符号(->)之前进行定义,并在表达式中使用。例如:(int a, int b) -> a + b 是接受两个整数参数并返回它们的和的Lambda表达式。总之,Lambda表达式提供了一种简洁的方式来传递行为作为参数,并且可以接受不同类型的参数。<span class="em">1</span><span class="em">2</span><span class="em">3</span>

四: Lambda表达式的返回类型是如何推导的?

Lambda表达式的返回类型是通过上下文推导得出的。根据Java语言规范,当Lambda表达式只有一条语句时,会自动推导返回类型。如果Lambda表达式有多条语句,则需要显式指定返回类型。 在Lambda表达式的语法中,返回类型通常是可以省略的,编译器会根据上下文自动推导出返回类型。 Lambda表达式的返回类型推导是通过invokedynamic指令实现的。

<span class="em">1</span><span class="em">2</span><span class="em">3</span>

Lambda表达式的底层

class Rate
{
public:
	Rate(double rate) : _rate(rate)
	{}

	double operator()(double money, int year)
	{
		return money * _rate * year;
	}

private:
	double _rate;
};

//lambda_uuid  
//uuid--Universally Unique Identifier,即通用唯一识别码。
class lambda_xxxx
{
};
int main()
{
	// 函数对象
	double rate = 0.49;
	Rate r1(rate);
	r1(10000, 2);

	// 仿函数lambda_uuid
	// lambda -> lambda_uuid
	auto r2 = [=](double monty, int year)->double{return monty*rate*year; };
	r2(10000, 2);

	auto r3 = [=](double monty, int year)->double{return monty*rate*year; };
	r3(10000, 2);

	return 0;
}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值