C++中的lambda表达式基本用法

C++ Lambda表达式基本用法

创建一个匿名函数并执行。Objective-C采用的是上尖号^,而C++ 11采用的是配对的方括号[]。实例如下:

1
2
3
4
5
6
7
8
9
#include <iostream>
using namespace std;
 
int main()
{
     []{
         cout << "Hello,Worldn" ;
     }();
}

我们也可以方便的将这个创建的匿名函数赋值出来调用:

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
using namespace std;
 
int main()
{
     int i = 1024;
     auto func = []( int i) { // (int i) 是指传入改匿名函数的参数
         cout << i;
     };
     func(i);
}

捕获选项

  • [] Capture nothing (or, a scorched earth strategy?)
  • [&] Capture any referenced variable by reference
  • [=] Capture any referenced variable by making a copy
  • [=, &foo] Capture any referenced variable by making a copy, but capture variable foo by reference
  • [bar] Capture bar by making a copy; don’t copy anything else
  • [this] Capture the this pointer of the enclosing class

[] 不捕获任何变量

1
2
3
4
5
6
7
8
9
#include <iostream>
using namespace std;
 
int main()
{
     int i = 1024;
     auto func = [] { cout << i; };
     func();
}

vs 报错
error C3493: 无法隐式捕获“i”,因为尚未指定默认捕获模式
error C2064: 项不会计算为接受 0 个参数的函数

g++ 报错:
error: ‘i’ is not captured

要直接沿用外部的变量需要在 [] 中指名捕获。

[=] 拷贝捕获

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
using namespace std;
 
int main()
{
     int i = 1024;
     auto func = [=]{  // [=] 表明将外部的所有变量拷贝一份到该函数内部
         cout << i;
     };
     func();
}

结果:
1024

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;
 
int main()
{
     int i = 1024;
     auto fun1 = [=]{
         // fun1 内存在 i
         cout << i; // 1024
         auto fun2 = []{ // 未指名捕获, i 不存在
             cout << i;
         };
         fun2();
     };
     fun1();
}

[&] 引用捕获

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;
 
int main()
{
     int i = 1024;
     cout << &i << endl;
     auto fun1 = [&]{
         cout << &i << endl;
     };
     fun1();
}

结果:
0x28ff0c
0x28ff0c

[=, &] 拷贝与引用混合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;
 
int main()
{
     int i = 1024, j = 2048;
 
     cout << "i:" << &i << endl;
     cout << "j:" << &j << endl;
 
     auto fun1 = [=, &i]{ // 默认拷贝外部所有变量,但引用变量 i
         cout << "i:" << &i << endl;
         cout << "j:" << &j << endl;
     };
     fun1();
}
1
 

结果
outside i:0x28ff0c
outside j:0x28ff08
inside i:0x28ff0c
inside j:0x28ff04

[bar] 指定引用或拷贝

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
using namespace std;
 
int main()
{
     int i = 1024, j = 2048;
 
     cout << "outside i value:" << i << " addr:" << &i << endl;
 
     auto fun1 = [i]{
         cout << "inside  i value:" << i << " addr:" << &i << endl;
         // cout << j << endl; // j 未捕获
     };
     fun1();
}

结果:
outside i value:1024 addr:0x28ff08
inside i value:1024 addr:0x28ff04

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
using namespace std;
 
int main()
{
     int i = 1024, j = 2048;
 
     cout << "outside i value:" << i << " addr:" << &i << endl;
 
     auto fun1 = [&i]{
         cout << "inside  i value:" << i << " addr:" << &i << endl;
         // cout << j << endl; // j 未捕获
     };
     fun1();
}

结果:
outside i value:1024 addr:0x28ff08
inside i value:1024 addr:0x28ff08

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;
 
int main()
{
     int i = 1024, j = 2048, k;
 
     cout << "outside i:" << &i << endl;
     cout << "outside j:" << &j << endl;
 
     auto fun1 = [i, &j]{
         cout << "inside  i:" << &i << endl;
         cout << "inside  j:" << &j << endl;
         // cout << k; // k 未捕获
     };
     fun1();
}

结果:
outside i:0x28ff0c
outside j:0x28ff08
inside i:0x28ff00
inside j:0x28ff08

[this] 捕获 this 指针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
using namespace std;
 
class test
{
public :
     void hello() {
         cout << "test hello!n" ;
     };
     void lambda() {
         auto fun = [ this ]{ // 捕获了 this 指针
             this ->hello(); // 这里 this 调用的就是 class test 的对象了
         };
         fun();
     }
};
 
int main()
{
     test t;
     t.lambda();
}

关于mutable:

  • mutable :允许 body 修改以复制捕获的参数,及调用其非 const 成员函数

也就是说:

按值捕获时,加上mutable才能改变lambda表达式中的值,加mutable时前边必须加()

int main()
{
	int i = 1024;
	cout << i << endl;
	auto fun1 = [=]()mutable{
		i = 213;
		cout << i << endl;
	};
	fun1();
	cout << i << endl;
	return 0;
}

按引用捕获时,不加mutable也可以

int main()
{
	int i = 1024;
	cout << i << endl;
	auto fun1 = [&]{
		i = 213;
	};
	fun1();
	cout << i << endl;
	return 0;
}
lambda表达式在函数式编程理论里,和Python、C++这样语言的实践中意义略有不同。对于Python和C++这样的语言来说,Lambda表达式就是:能嵌入到其他表达式当中的匿名函数(闭包)。


它的第一个重要意义是可以在表达式当中直接定义一个函数,而不需要将定义函数和表达式分开,这样有助于将逻辑用更紧凑的方式表达出来。


它的第二个重要意义是引入了闭包。基本上来说常见的支持lambda表达式的语言里,不存在不支持闭包的lambda表达式;从函数式编程的角度来说,支持闭包也是很重要的。闭包是指将当前作用域中的变量通过值或者引用的方式封装到lambda表达式当中,成为表达式的一部分,它使你的lambda表达式从一个普通的函数变成了一个带隐藏参数的函数。


它的第三个重要意义(如果有的话)是允许函数作为一个对象来进行传递。某些语言由于历史原因,只有匿名函数可以作为对象传递,而具名函数不可以,比如PHP。

猜你喜欢

转载自blog.csdn.net/flyyufenfei/article/details/79414240
今日推荐