C中只有傳值(PV)和傳地址(PP)。有些語言僅僅有傳地址,沒有傳值。好象FORTRAN就是。實際上從匯編開始理解,傳遞(包括參數和返回)要么是PV要么是PP。那么引用是什么東西?
引用是C++不得以產生的概念。如果沒有C的PV,如FORTRAN那樣全是引用(一種PP),也就不會出現引用的概念。
下面的小程序和對應的匯編可以說明引用本質。從func0和func1的調用可以看出引用本質就是地址傳遞(PP)。2個函數調用的匯編一樣的。func2返回引用,實際是返回地址,也是地址傳遞(PP)。
那么引用有好處嗎?我個人意見,不多。除非萬不得已非用不可,建議千萬不要使用。使用了,后果是讓簡單的程序無法讀懂(不是因為引用概念復雜),尤其是分模塊的情況下。比如:
int i = 1;
return i;
的本意很清楚,可以有引用的情況下,這2行的意義是不確定的。比如往前看才能確定。
function(i); 也是一樣,本來清楚的東西變為不確定。
實際上引用就是PP,但是一種用編譯器做了偽裝的PP。因此使程序更不容易讀。
[CODE]
#include <stdio.h>
int func0(int &i)
{
i++;
return 100;
}
int func1(int *ip)
{
(*ip) ++;
return 101;
}
int& func2(int i)
{
static int ii = 123;
return ii;
}
main()
{
int i, j;
i = 4;
j = 104;
j = func0(i);
//printf("i = %d j = %d\n", i, j);
j = func1(&i);
//printf("i = %d j = %d\n", i, j);
j = func2(9);
//printf("i = %d j = %d\n", i, j);
}
.file "t2.c"
.text
.align 2
.globl _Z5func0Ri
.type _Z5func0Ri,@function
_Z5func0Ri:
.LFB2:
pushl %ebp
.LCFI0:
movl %esp, %ebp
.LCFI1:
movl 8(%ebp), %eax
incl (%eax)
movl $100, %eax
leave
ret
.LFE2:
.Lfe1:
.size _Z5func0Ri,.Lfe1-_Z5func0Ri
.align 2
.globl _Z5func1Pi
.type _Z5func1Pi,@function
_Z5func1Pi:
.LFB4:
pushl %ebp
.LCFI2:
movl %esp, %ebp
.LCFI3:
movl 8(%ebp), %eax
incl (%eax)
movl $101, %eax
leave
ret
.LFE4:
.Lfe2:
.size _Z5func1Pi,.Lfe2-_Z5func1Pi
.align 2
.globl _Z5func2i
.type _Z5func2i,@function
_Z5func2i:
.LFB6:
pushl %ebp
.LCFI4:
movl %esp, %ebp
.LCFI5:
subl $4, %esp
.LCFI6:
movl $123, -4(%ebp)
leal -4(%ebp), %eax
leave
ret
.LFE6:
.Lfe3:
.size _Z5func2i,.Lfe3-_Z5func2i
.align 2
.globl main
.type main,@function
main:
.LFB8:
pushl %ebp
.LCFI7:
movl %esp, %ebp
.LCFI8:
subl $8, %esp
.LCFI9:
andl $-16, %esp
movl $0, %eax
subl %eax, %esp
movl $4, -4(%ebp)
movl $104, -8(%ebp)
subl $12, %esp
leal -4(%ebp), %eax
pushl %eax
.LCFI10:
call _Z5func0Ri
addl $16, %esp
movl %eax, -8(%ebp)
subl $12, %esp
leal -4(%ebp), %eax
pushl %eax
call _Z5func1Pi
addl $16, %esp
movl %eax, -8(%ebp)
subl $12, %esp
pushl $9
call _Z5func2i
addl $16, %esp
movl (%eax), %eax
movl %eax, -8(%ebp)
movl $0, %eax
leave
ret
.LFE8:
.Lfe4:
.size main,.Lfe4-main
.ident "GCC: (GNU) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)"
[/CODE]