引用的实现实质上跟指针是一样的,如下:
//------------------------------------------------
#include <iostream>
using namespace std;
int main()
{
int a = 3;
int &ref_a = a;
ref_a += 2;
return 0;
}
//-----------------------------------------------
1: #include <iostream>
2:
3: using namespace std;
4:
5: int main()
6: {
00401030 55 push ebp
00401031 8B EC mov ebp,esp
00401033 83 EC 48 sub esp,48h
00401036 53 push ebx
00401037 56 push esi
00401038 57 push edi
00401039 8D 7D B8 lea edi,[ebp-48h]
0040103C B9 12 00 00 00 mov ecx,12h
00401041 B8 CC CC CC CC mov eax,0CCCCCCCCh
00401046 F3 AB rep stos dword ptr [edi]
7: int a = 3;
00401048 C7 45 FC 03 00 00 00 mov dword ptr [ebp-4],3 ; a存储在内存中的[ebp-4]处,初值为3
8: int &ref_a = a;
0040104F 8D 45 FC lea eax,[ebp-4] ; 取[ebp-4]地址给eax,(ref_a = &a)
00401052 89 45 F8 mov dword ptr [ebp-8],eax ; 将此地址值保存在[ebp-8]处,作为ref_a的内容(也就是其所指向的变量的地址)
9:
10: ref_a += 2;
00401055 8B 4D F8 mov ecx,dword ptr [ebp-8] ; 地址赋给ecx
00401058 8B 11 mov edx,dword ptr [ecx] ; 取ecx中保存的地址处的值赋给edx(也就是a的值)
0040105A 83 C2 02 add edx,2 ; 加2
0040105D 8B 45 F8 mov eax,dword ptr [ebp-8] ; 将a的地址赋给eax (eax = &a)
00401060 89 10 mov dword ptr [eax],edx ; 把计算结果保存到a的地址空间处,实现了对a的改变
11: return 0;
00401062 33 C0 xor eax,eax
12: }
---------------------------------------------
观察宏的反汇编代码
//---------------------------------------------
#include <stdio.h>
#define CMP(x,y) ( (x) > (y) ? 1 : -1)
int main()
{
int r = CMP(2,1+2);
printf("%d/n", r);
return 0;
}
//-----------------------------------------------
$gcc -O2 -S macro_disasm.c
GCC优化编译后:
.file "macro_disasm.c"
gcc2_compiled.:
___gnu_compiled_c:
.text
LC0:
.ascii "%d/12/0"
.p2align 2
.globl _main
_main:
pushl %ebp
movl %esp,%ebp
subl $8,%esp
addl $-8,%esp
pushl $-1 ; 居然直接在汇编代码中显示结果-1
pushl $LC0
call _printf
xorl %eax,%eax
movl %ebp,%esp
popl %ebp
ret
$gcc -S macro_disasm.c
不用优化编译:
.file "macro_disasm.c"
gcc2_compiled.:
___gnu_compiled_c:
.text
LC0:
.ascii "%d/12/0"
.p2align 2
.globl _main
_main:
pushl %ebp
movl %esp,%ebp
subl $24,%esp
movl $-1,-4(%ebp) ; 仍然直接将结果-1放入内存
addl $-8,%esp
movl -4(%ebp),%eax ; 读出结果-1,进栈
pushl %eax
pushl $LC0
call _printf
addl $16,%esp
xorl %eax,%eax
jmp L2
.p2align 4,,7
L2:
movl %ebp,%esp
popl %ebp
ret
宏在编译过程中就被编译器直接替换,不生成额外的执行代码。