lambda续集——2

隐式捕获:

出了显式列出我们希望使用的来自函数的变量外,还可以让编译器根据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,用函数替代就不那么容易了。

posted @ 2017-03-24 09:43  Crystal_Guang  阅读(216)  评论(0编辑  收藏  举报