Lambda表达式提供了匿名函数这个概念,可以使您在一个函数中书写另一个匿名的函数体
先来看下如何在VC2010中书写Lambda表达式
[捕捉项表](参数表)->返回类型{函数体}
捕捉项表中在变量前添加&操作符表示捕捉引用,添加=表示捕捉值
参数表与"->"和后面的返回类型是可选的编译器会由函数体内的return语句判断返回类型,当返回类型很复杂时编译器无法判断,则必须手动给出!
下面举个简单的例子:
1 #include <stdio.h>
2
3 int main()
4 {
5 int a = 100;
6 [a]{
7 printf("%d\n",a);
8 }();
9 return 0;
10 }
然后在VS2010提示中编译它:cl /FAs a.cpp
/FAs参数指定了输出汇编文件a.asm.
然后我们来看一下它生成的汇编代码:
1 ; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.30319.01
2
3 TITLE D:\a.cpp
4 .686P
5 .XMM
6 include listing.inc
7 .model flat
8
9 INCLUDELIB LIBCMT
10 INCLUDELIB OLDNAMES
11
12 PUBLIC ??R<lambda0>@?A0x428ab923@@QBEXXZ ; `anonymous namespace'::<lambda0>::operator()
13 PUBLIC ??0<lambda0>@?A0x428ab923@@QAE@ABH@Z ; `anonymous namespace'::<lambda0>::<lambda0>
14 PUBLIC _main
15 ; Function compile flags: /Odtp
16 ; File d:\a.cpp
17 _TEXT SEGMENT
18 $T3875 = -8 ; size = 4
19 _a$ = -4 ; size = 4
20 _main PROC
21
22 ; 4 : {
23
24 push ebp
25 mov ebp, esp
26 sub esp, 8
27
28 ; 5 : int a = 100;
29
30 mov DWORD PTR _a$[ebp], 100 ; 00000064H
31
32 ; 6 : [a]{
33 ; 7 : printf("%d\n",a);
34 ; 8 : }();
35
36 lea eax, DWORD PTR _a$[ebp]
37 push eax
38 lea ecx, DWORD PTR $T3875[ebp]
39 call ??0<lambda0>@?A0x428ab923@@QAE@ABH@Z ; `anonymous namespace'::<lambda0>::<lambda0>
40 mov ecx, eax
41 call ??R<lambda0>@?A0x428ab923@@QBEXXZ ; `anonymous namespace'::<lambda0>::operator()
42
43 ; 9 : return 0;
44
45 xor eax, eax
46
47 ; 10 : }
48
49 mov esp, ebp
50 pop ebp
51 ret 0
52 _main ENDP
53 ; Function compile flags: /Odtp
54 _TEXT ENDS
55 ; COMDAT ??0<lambda0>@?A0x428ab923@@QAE@ABH@Z
56 _TEXT SEGMENT
57 _this$ = -4 ; size = 4
58 __A$ = 8 ; size = 4
59 ??0<lambda0>@?A0x428ab923@@QAE@ABH@Z PROC ; `anonymous namespace'::<lambda0>::<lambda0>, COMDAT
60 ; _this$ = ecx
61
62 ; 8 : }();
63
64 push ebp
65 mov ebp, esp
66 push ecx
67 mov DWORD PTR _this$[ebp], ecx
68 mov eax, DWORD PTR _this$[ebp]
69 mov ecx, DWORD PTR __A$[ebp]
70 mov edx, DWORD PTR [ecx]
71 mov DWORD PTR [eax], edx
72 mov eax, DWORD PTR _this$[ebp]
73 mov esp, ebp
74 pop ebp
75 ret 4
76 ??0<lambda0>@?A0x428ab923@@QAE@ABH@Z ENDP ; `anonymous namespace'::<lambda0>::<lambda0>
77 _TEXT ENDS
78 PUBLIC ??_C@_03PMGGPEJJ@?$CFd?6?$AA@ ; `string'
79 EXTRN _printf:PROC
80 ; COMDAT ??_C@_03PMGGPEJJ@?$CFd?6?$AA@
81 CONST SEGMENT
82 ??_C@_03PMGGPEJJ@?$CFd?6?$AA@ DB '%d', 0aH, 00H ; `string'
83 ; Function compile flags: /Odtp
84 CONST ENDS
85 ; COMDAT ??R<lambda0>@?A0x428ab923@@QBEXXZ
86 _TEXT SEGMENT
87 _this$ = -4 ; size = 4
88 ??R<lambda0>@?A0x428ab923@@QBEXXZ PROC ; `anonymous namespace'::<lambda0>::operator(), COMDAT
89 ; _this$ = ecx
90
91 ; 6 : [a]{
92
93 push ebp
94 mov ebp, esp
95 push ecx
96 mov DWORD PTR _this$[ebp], ecx
97
98 ; 7 : printf("%d\n",a);
99
100 mov eax, DWORD PTR _this$[ebp]
101 mov ecx, DWORD PTR [eax]
102 push ecx
103 push OFFSET ??_C@_03PMGGPEJJ@?$CFd?6?$AA@
104 call _printf
105 add esp, 8
106
107 ; 8 : }();
108
109 mov esp, ebp
110 pop ebp
111 ret 0
112 ??R<lambda0>@?A0x428ab923@@QBEXXZ ENDP ; `anonymous namespace'::<lambda0>::operator()
113 _TEXT ENDS
114 END
115
由汇编代码可以看到先为Lambda函数生成了一个匿名对象,然后调用了()的操作符重载函数调用这个匿名函数.
由此我们得出结论:调用一个匿名函数并没有调用一个存在的函数或是一个类的成员函数快,只是书写更方便罢了.
然后我们修改一下代码,将匿名函数先赋给一个匿名函数指针,然后调用.
1 #include <stdio.h>
2
3 int main()
4 {
5 int a = 100;
6 auto ptr = [a]{
7 printf("%d\n",a);
8 };
9 ptr();
10 return 0;
11 }
编译后得到代码:
1 ; Listing generated by Microsoft (R) Optimizing Compiler Version 16.00.30319.01
2
3 TITLE D:\a.cpp
4 .686P
5 .XMM
6 include listing.inc
7 .model flat
8
9 INCLUDELIB LIBCMT
10 INCLUDELIB OLDNAMES
11
12 PUBLIC ??R<lambda0>@?A0x428ab923@@QBEXXZ ; `anonymous namespace'::<lambda0>::operator()
13 PUBLIC ??0<lambda0>@?A0x428ab923@@QAE@ABH@Z ; `anonymous namespace'::<lambda0>::<lambda0>
14 PUBLIC _main
15 ; Function compile flags: /Odtp
16 ; File d:\a.cpp
17 _TEXT SEGMENT
18 _ptr$ = -8 ; size = 4
19 _a$ = -4 ; size = 4
20 _main PROC
21
22 ; 4 : {
23
24 push ebp
25 mov ebp, esp
26 sub esp, 8
27
28 ; 5 : int a = 100;
29
30 mov DWORD PTR _a$[ebp], 100 ; 00000064H
31
32 ; 6 : auto ptr = [a]{
33 ; 7 : printf("%d\n",a);
34 ; 8 : };
35
36 lea eax, DWORD PTR _a$[ebp]
37 push eax
38 lea ecx, DWORD PTR _ptr$[ebp]
39 call ??0<lambda0>@?A0x428ab923@@QAE@ABH@Z ; `anonymous namespace'::<lambda0>::<lambda0>
40
41 ; 9 : ptr();
42
43 lea ecx, DWORD PTR _ptr$[ebp]
44 call ??R<lambda0>@?A0x428ab923@@QBEXXZ ; `anonymous namespace'::<lambda0>::operator()
45
46 ; 10 : return 0;
47
48 xor eax, eax
49
50 ; 11 : }
51
52 mov esp, ebp
53 pop ebp
54 ret 0
55 _main ENDP
56 ; Function compile flags: /Odtp
57 _TEXT ENDS
58 ; COMDAT ??0<lambda0>@?A0x428ab923@@QAE@ABH@Z
59 _TEXT SEGMENT
60 _this$ = -4 ; size = 4
61 __A$ = 8 ; size = 4
62 ??0<lambda0>@?A0x428ab923@@QAE@ABH@Z PROC ; `anonymous namespace'::<lambda0>::<lambda0>, COMDAT
63 ; _this$ = ecx
64
65 ; 8 : };
66
67 push ebp
68 mov ebp, esp
69 push ecx
70 mov DWORD PTR _this$[ebp], ecx
71 mov eax, DWORD PTR _this$[ebp]
72 mov ecx, DWORD PTR __A$[ebp]
73 mov edx, DWORD PTR [ecx]
74 mov DWORD PTR [eax], edx
75 mov eax, DWORD PTR _this$[ebp]
76 mov esp, ebp
77 pop ebp
78 ret 4
79 ??0<lambda0>@?A0x428ab923@@QAE@ABH@Z ENDP ; `anonymous namespace'::<lambda0>::<lambda0>
80 _TEXT ENDS
81 PUBLIC ??_C@_03PMGGPEJJ@?$CFd?6?$AA@ ; `string'
82 EXTRN _printf:PROC
83 ; COMDAT ??_C@_03PMGGPEJJ@?$CFd?6?$AA@
84 CONST SEGMENT
85 ??_C@_03PMGGPEJJ@?$CFd?6?$AA@ DB '%d', 0aH, 00H ; `string'
86 ; Function compile flags: /Odtp
87 CONST ENDS
88 ; COMDAT ??R<lambda0>@?A0x428ab923@@QBEXXZ
89 _TEXT SEGMENT
90 _this$ = -4 ; size = 4
91 ??R<lambda0>@?A0x428ab923@@QBEXXZ PROC ; `anonymous namespace'::<lambda0>::operator(), COMDAT
92 ; _this$ = ecx
93
94 ; 6 : auto ptr = [a]{
95
96 push ebp
97 mov ebp, esp
98 push ecx
99 mov DWORD PTR _this$[ebp], ecx
100
101 ; 7 : printf("%d\n",a);
102
103 mov eax, DWORD PTR _this$[ebp]
104 mov ecx, DWORD PTR [eax]
105 push ecx
106 push OFFSET ??_C@_03PMGGPEJJ@?$CFd?6?$AA@
107 call _printf
108 add esp, 8
109
110 ; 8 : };
111
112 mov esp, ebp
113 pop ebp
114 ret 0
115 ??R<lambda0>@?A0x428ab923@@QBEXXZ ENDP ; `anonymous namespace'::<lambda0>::operator()
116 _TEXT ENDS
117 END
118
和上面的直接调用并无差别,因为一个匿名函数含有一个隐藏的对象.
应此__asm call ptr;这样调用是错误的!因为你无法用call指令来调用一个对象的成员函数.
posted on 2011-02-17 16:32
lwch 阅读(2664)
评论(0) 编辑 收藏 引用 所属分类:
其他