隐式捕获:
出了显式列出我们希望使用的来自函数的变量外,还可以让编译器根据lambda体中的代码来推断我们要使用哪些变量。为了指示编译器推断捕获列表,应在捕获列表中写一个&或=。&告诉编译器采用引用捕获方式,=告诉编译器采用值捕获方式。我们可以混合使用隐式或显式捕获,在此条件下,捕获列表的第一个元素必须是一个&或=。当混合使用隐式和显式捕获时,显式捕获的变量必须使用与隐式捕获不同的方式。即,如果隐式捕获时引用(&)方式,则显式捕获名变量必须使用值捕获方式,因此不能在显式捕获名字前使用&;如果是隐式捕获时值(=)方式,显式捕获变量名必须采用引用方式,即在名字前加&。
eg:
1 #include<iostream>
2 using namespace std;
3
4 int main()
5 {
6 /*隐式引用捕获*/
7 int ma = 10;
8 int mma = 10;
9 auto f= [&] {return ma+mma; };
10 ma = 1;
11 cout << f() << endl;
12
13 /*隐式值捕获*/
14 int a = 10;
15 int aa = 10;
16 auto ff = [=] {return a+aa; };
17 a = 1;
18 cout << ff() << endl;
19
20 /*混合捕获,引用在前*/
21 int i = 10;
22 int j = 100;
23 auto fff = [&,j] {return i+j; };
24 //auto fff = [&i, =] {return i + j; }; err
25 //auto fff = [&i, &] {return i + j; }; err
26 i = 1;
27 cout << fff() << endl;
28
29 /*混合捕获,值在前*/
30 int m = 10;
31 int n = 100;
32 auto ffff = [=, &n] {return m + n; };
33 n = 1;
34 cout << ffff() << endl;
35
36 /*混合捕获的思考,多个变量,可以隐式捕获,针对特殊变量,单独指定*/
37 int q = 1, w = 10, e = 20, r = 30;
38 /*我想除了e变量,其余的都用值捕获*/
39 auto fffff = [=, &e] {return q+w+e+r; };
40 e = 100;
41 cout << fffff() << endl;
42 return 0;
43 }
可变lambda:
默认情况下,对于一个值拷贝的变量,lambda不会改变其值,如果我们希望能改变一个被捕获的变量的值,就必须在参数列表后加上mutable。因此,可变lambda能省略参数列表。
1 #include<iostream>
2 using namespace std;
3
4 int main()
5 {
6 int ma = 10;
7 auto f= [=] ()mutable {return ++ma; };
8 cout << f() << endl;
9 return 0;
10 }
一个引用捕获能否改变变量的值依赖于此引用指向的是一个const类型还是一个非const类型。
指定lambda返回类型:
默认情况下,如果lambda体包含return之外的任何语句,则编译器假定此lambda返回void。与其他返回void的函数类似,被推断返回void的lambda不能返回值。
1 #include<iostream>
2 using namespace std;
3
4 int main()
5 {
6 auto f = [](int* a)->int * { if (*a > 0)return a; else return NULL; };
7 cout << f(NULL) << endl;
8 return 0;
9 }
不用位置返回类型将报错。但是如果返回类型都是一种类型,比如上诉两个return,都return一种类型,是可以推断的,但是吐过return类型不同,将要使用尾置返回类型强制指定,在不止单纯一条return语句时,建议最好使用尾置返回类型。
对于那种只在一两个地方使用的简单操作,lambda表达式是很有用的。但如果我们需要在很多地方使用相同的操作,通常应该定义一个函数,而不是多次编写相同的lambda表达式。类似的,如果一个操作需要很多语句完成,通常使用函数更好。如果一个lambda捕获列表为空,通常可以用函数来代替它。但是对于捕获局部变量的lambda,用函数替代就不那么容易了。