C++新特性语法总结----lambda表达式详细总结



lambda表达式基础

lamda表达式就是匿名函数(没有名字的函数),lambda表达式基本语法如下:

[捕获列表](参数列表) mutable(可选) 异常属性 -> 返回类型
{
	//函数体其中,仅有“[]{}”是必须的,其他全部可以省略不写。lambda的使用,和函数类似,先要定义,然后调用。
}

参数列表:

1、参数列表和普通函数的参数列表一样,可以是值、引用、const引用等,也是作为形参;

2、如果是非const引用,函数体内部可以修改引用的值;

3、与普通函数不同,lambda表达式的参数不能有默认值。

函数体:

1、可以使用参数列表中传递的参数;

2、可以直接访问静态局部变量,以及全局变量;

3、不能直接访问非静态局部变量;

4、可以使用捕捉列表里捕捉的局部变量;

5、可以在函数体中对全局变量和静态局部变量修改。

捕获列表:

1、捕捉列表中直接写非静态变量的变量名,函数体中便可访问;

2、与参数列表不同,不需要在变量名前加上类型;

3、如果有多个变量,用","隔开;

4、只能捕捉在lambda定义之前已经定义的非静态局部变量;

5、直接写变量名,为值捕获;想要引用方式捕获,则在变量名前加上"&"。

[capture](params) opt -> ret {body; };

//最简单的一个例子:
//普通函数
int Foo(int a, int b){
	return a + b;
}
//lamda表达式等价于 c = Foo(1, 2);
int c = [](int a, int b)-> int {
	return a + b;
}(1, 2);

//另外一种形式:
auto f = [](int a, int b)-> int {
	return a + b;
}
c = f(1, 2);

两个lamda表达式之间是可以嵌套的

int c = [](int n){
	return [n](int x){ //内部捕获外部lambda表达式参数n
		return n + x;
	}(1);
}(2);

mutable

int main()
{
	int t = 10;
	auto f = [t](){  //Error!! 此时捕获的t是一个常量类型不能修改
		return ++t;
	}
	auto f = [t]() mutable{  //Success!!
		return ++t;
	}
	
	std::cout << f() << std::endl;  //  11
	std::cout << f() << std::endl;  //   12
	std::cout << t << std::endl;    //    10
}

为什么第一次第二次输出为11,12,然而t的值还是为10?首先这个 t(捕获列表)只是按值来捕获的,所以 t 在lambda内部的修改不影响外部的 t 的值。其次,内部捕获列表的 t 和外部的 t 不是同一个变量,不是同一个地址!当使用mutable对 t 进行捕获的时候,那么在这个匿名函数的内部,它是独自拥有的,是独一无二的每次进来都是对相同的 t 进行 ++ , 所以第一次第二次输出为11 12。

捕获列表的用法

按值捕获:

int main()
{
	int t = 10;
	auto f = [t](){  
		std::cout << t << std::endl;
	};
	t = 11;
	f();
}

结果输出为10,捕获的是声明匿名函数时,捕获列表参数的值。可以理解为,值捕获创建了一个临时对象,拷贝了原变量的值,之后,这个临时变量与原来的变量再无任何瓜葛,lambda中操作的是这个临时变量。

而引用捕获,创建的是一个引用/指针,指向了原来的变量,lambda函数体中操作的就是变量本身。

按引用捕获:

int main()
{
	int t = 10;
	auto f2 = [&t](){  
		std::cout << t << std::endl;
		t = 13;
	};
	t = 11;
	f2();
	std::cout << t << std::endl;
}

结果输出为 11 ,13

按引用捕获在实际应用中是有风险的,主要原因是lambda表达式在被创建后到被执行前这段期间里,这个引用有可能会变得不复存在了,这时候就很难保证这个引用变量在执行的时候一定存在。所以除非我们能确保它在lambda执行的时候是一定存在的,否则应该尽量避免用按引用捕获。

隐式捕获:

前面介绍的,将变量名写入捕获列表,为显式捕获。如果lambda中需要用到的非静态局部变量非常多,全部写入捕获列表,就会显得非常臃肿,有简便写法,即为隐式捕获。

1、空。没有使用任何函数对象参数。

2、=。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量)。

3、&。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是引用传递方式(相当于编译器自动为我们按引用传递了所有局部变量)。

4、this。函数体内可以使用Lambda所在类中的成员变量。
5、a。将a按值进行传递。按值进行传递时,函数体内不能修改传递进来的a的拷贝,因为默认情况下函数是const的。要修改传递进来的a的拷贝,可以添加mutable修饰符。

6、&a。将a按引用进行传递。

7、a, &b。将a按值进行传递,b按引用进行传递。

8、=,&a, &b。除a和b按引用进行传递外,其他参数都按值进行传递。

9、&, a, b。除a和b按值进行传递外,其他参数都按引用进行传递。

注意:

1、捕获列表的形式为"[=]“(值捕获)或者”[&]“(引用捕获);
2、捕获列表里不能同时写”=“和”&“,即”[=, &]"是非法的;
3、隐式捕获可以和显式捕获搭配使用,但不能和同类型的显示捕获一起使用。即隐式值捕获只能搭配显式引用捕获,隐式引用捕获只能搭配显式值

返回值

如果指定了lambda的返回值类型,则只需要函数体中return的类型可以隐式转换成指定的返回值类型,编译就可以通过编译,类型不匹配可能会给出警告:

int main()
{
	auto fun = [](int i) -> int{
		if (i>0)
			return true;
		else
			return 11.14;
	};
	std::cout << fun(-3) << std::endl;
	return 0;
}

编译后会有警告:

“return”:从"double"到"int"可能会丢失数据

如果没有显式指定返回值,编译器会以第一个return语句的类型作为返回值类型,之后的所有return语句,必须是此类型,否则会直接报错。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
C++ lambda 表达式的语法如下: ``` [capture](parameters) -> return_type { body } ``` 其中: - `capture`:捕获列表,用于指定 lambda 表达式内部可访问的外部变量。捕获列表可以为空,也可以使用`[]`、`[=]`、`[&]`等形式进行指定。 - `[]`:不捕获任何外部变量。 - `[=]`:以值方式捕获所有外部变量。 - `[&]`:以引用方式捕获所有外部变量。 - `[var]`:以值方式捕获变量 `var`。 - `[&var]`:以引用方式捕获变量 `var`。 - `parameters`:参数列表,用于指定 lambda 表达式的参数。 - `return_type`:返回类型,用于指定 lambda 表达式的返回类型。可以省略,编译器会自动推导。 - `body`:函数体,用于实现 lambda 表达式的逻辑。 下面是一个 lambda 表达式的示例: ```cpp #include <iostream> int main() { int x = 5; int y = 10; // Lambda 表达式捕获外部变量 x,并接受一个参数 a auto lambda = [x](int a) { return x + a; }; int result = lambda(y); std::cout << "Result: " << result << std::endl; // 输出: 15 return 0; } ``` 在上面的示例中,lambda 表达式 `[x](int a) { return x + a; }` 捕获了外部变量 `x`,并接受一个参数 `a`。在 lambda 表达式内部,它实现了将 `x` 和 `a` 相加的逻辑,然后通过调用 `lambda(y)` 来计算结果,最后将结果输出到控制台。 请注意,由于 lambda 表达式的返回类型可以自动推导,所以在这个示例中我们没有显式指定返回类型。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风风风风挽丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值