这也算是一个老生常谈的问题,写这个其实就是想趁着暑假把博客丰富一下。
咱随便在谷哥、度娘、病软引擎上搜搜都可以得到各种关于引用的解释,无非就是“引用不同于指针,引用是一个变量的别名”“使用引用就是使用变量本身”“”等等这些,于是大量的概念轰炸下,“引用不占用空间”这一言论貌似也是到处都有,流传甚广,几近泛滥,已经有淹没真想之势。于是本着追逐真理之精神,把引用究竟占不占空间这事儿解释清楚,至于引用与指针是不是不同的东西,这一哲学问题见仁见智,咱们就不去探究,真想搞清楚还是得问C++的爸爸。
真要搞清楚,还得从代码本身出发。
int main() { int a=10; int* b=&a; a=30; *b=20; }
先看看这段代码有什么意义?是不是觉得没有什么意义?嗯,确实没什么意义,从表面上也完全看不出什么来,当然了,如果您看出什么来了,那您一定要当什么都没看出来!
好了,要想知道这段代码做了什么,还得从汇编看起,毕竟从底层看起能都尽量多地绕过编译器,展示其真实行为,不失为一个学习基本概念的好办法。因为我用的是linux平台,所以我比较倾向于用AT&T汇编展示,如果您不熟悉,完全没关系,赶紧关掉网页,麻溜走人!。。。。。英雄留步,我这儿跟你开个玩笑活跃一下气氛,诶,诶,那位爷,能别抄起凳子么?
subl $16, %esp //分配空间 call ___main movl $10, 8(%esp) //把10存入变量a代表的空间 leal 8(%esp), %eax //将变量a的地址存入寄存器eax movl %eax, 12(%esp) //将变量a的地址存入另一块儿地址,这里即指针b movl $30, 8(%esp) //将30赋值给变量a movl 12(%esp), %eax //将变量a的地址赋值给寄存器eax movl $20, (%eax) //将20赋值给寄存器eax的值所代表的地址处,
通过注释(应该还算清晰吧),可以完整对应上面那段代码的行为,这里可以真切地从肌肤与体位上感受到其行为的确定性。可以看到,一切都在我们的掌控之中。
下面对代码进行一点小修改:
int main() { int a=10; int& b=a; a=30; b=20; }
经过对比,可以看到,仅仅是将指针换成了引用,嗯,从语义上看,其行为貌似发现了一些变化,但是在内部发生了什么呢?您请往下走:
subl $16, %esp call ___main movl $10, 8(%esp) leal 8(%esp), %eax movl %eax, 12(%esp) movl $30, 8(%esp) movl 12(%esp), %eax movl $20, (%eax)
なに!代码发生了什么变化?您看出变化来了吗?如果您看出来了,出门儿右拐大药房滴眼液来两滴。
可以看到汇编层面上,其行为没有任何变化,与指针是一模一样的,咱们就此打住,不用多想,指针要占用4字节的空间,您引用既然和指针是同样的东西,凭什么不占?嗯,其实就这么点事儿。
C++中的引用到底是什么