引用和指针,到底有什么不同呢?
区别
在c++当中,引用是别名,已经初始化就无法更改,而指针则是指向某一区域的内存的地址,是可以修改的。
而在函数当中,形参的传递分为值传递,引用传递和指针传递。其中,指针传递和引用传递都是可以避免复制数值的时候产生的不必要的复制花销。也拥有可以直接改变传入的参数的值的效果。那么,他们之间到底有没有什么区别呢?
引用传递与指针传递
首先,为了测试,我们先写了如下的代码。
1 | int global = 100; |
然后,再看看其中翻译过后的汇编代码。
1 | //funcRef |
不难看出,他们的操作是一样的,从%rdi中取出函数传递的值,然后,保存在自己的栈帧中,一顿操作后,再放回(%rax)所记录的内存当中(也就是值原本所在的内存位置)
那么,指针和引用的存储形式是一样的吗?
指针与引用在汇编中的形式
1 | 0000000000001169 <main>: |
这是main刚刚的代码的main函数。可以看出,无论是不是局部变量,还是全局变量,指针和引用的本质都是使用了相对应的内存地址而已。可以说,本质来说,引用和指针都是一个指针而已。
所以,引用和指针的区别确实只是体现在是否可以改变这一点上而已(或许还有指针用->,引用只需要.?)
其实,我们可以打开elf文件当中的符号表看看他们之间的关系
1 | 46: 0000000000004018 8 OBJECT GLOBAL DEFAULT 24 ptrGlobal // [24]=> .data |
其实不难看出,指针和原本的global都是存在.data条目当中的,也就是存在在内存当中的。而引用refGlobal却只是在只读可重定位条目当中,本身是不占有任何内存空间的。
因此,他们之间的区别虽然在汇编代码当中没有比较明确的体现出来,但是,在内存的占用上却是比较确切的体现了出来。
因此,当我们修改一下代码
1 | int global = 100; |
不难推测,传递到%rax当中的绝对是全局变量prtGlobal的值。
1 | 0000000000001169 <main>: |
事实确实如此。
因此,也可以看出,只有引用和指针在全局变量(或者静态变量)的时候会出现不同,因为,这些都是可以出现在符号表当中的内容。