您的位置:首页 > 其它

从变量到指针到引用

2017-05-11 10:46 232 查看
引用到底是什么东西,可能一直让大家比较疑惑。从《C++ primer》里总结一下,引用的特点如下:

1. 再熟悉不过的说法,引用是变量的别名,操作引用跟操作变量的效果是一样的;

2. 引用不是对象,因此,不会给引用分配内存空间;

3. 参数传递如果形参是引用,那么此时引用的表现就像指针一样,可以直接改变变量的值。

这三个特点听起来简单,但是如果深入思考一下,就不由得疑惑究竟是什么造成了引用的这些特点,而引用或者“别名”又到底是什么东西?

变量定义的特点:

1. 对于 int a 这条语句,编译器会分配一个 4 字节的内存单元(典型的32位机上,假设起始地址是0x124EFDD8),并将这个内存单元和 a 这个变量名绑定在一起;

2. 我们知道,编译的过程中,对于函数名、变量名等都会替换成相应的符号,所以我们假设编译后 a 变量名被替换为符号 L1,那么这个过程的示意如下:



3. 当我们访问变量 a 时,其实就是通过 L1 这个符号访问相应的内存单元的。所以,变量一旦定义之后,无论我们会把哪个变量赋给 a ,其实质只是把该变量的内容写到 0x124EFDD8 这块内存单元中而已,L1 和 0x124EFDD8 的绑定关系是永远不变的。

引用定义的特点:

1. 假设 int &aref = a 即 aref 是 变量 a 的引用,那么此时编译器对 aref 会做出怎样的行为呢?

2. 根据 “引用不是对象,不会分配内存单元” 的特征,我们可以得出结论,引用定义时,编译器没有为引用分配内存空间,只是简单的把引用替换为一个符号(我们假设是 L2);

3. 根据 “引用是变量的别名” 的特征,其实我们已经可以知道,编译器是把引用和变量的内存空间绑定起来了,即将L2 和 0x124EFDD8 绑定到一起,示意如下:



4. 当我们访问引用时,也是通过符号 L2 进行访问,所以,访问 aref 时最终访问的也是 0x124EFDD8 ,这样就解释了“操作引用和操作变量的效果是一样的”这一特点。

那么指针和引用的区别又在哪里呢?

1. 假设 int *p = &a 即定义指针 p 指向变量 a ;

2. 指针也是一个变量,所以编译器遇到指针时,也会为指针分配存储空间(假设是 0x3473AFB4),然后把替换后的符号(假设是 L3)和这一块内存单元绑定起来,同时,我们知道,指针的内容是变量的地址,所以可得如下示意图:



3. 从上图我们就可以明白,当我们访问指针时,通过 L3 访问到 0x3473AFB4 ,但是我们如果想要访问它所指向的对象时,就要进行解引用(*p) 才能访问到变量 a ,而引用就不需要解引用这一操作,因为它直接就指向了变量
a;

指针和引用在参数传递时,编译器的行为:

1. 两种情况下都不用复制操作对象,也都可以修改操作对象;

2. 但是实现机制不同,以指针为参数时,编译器同样对指针进行了值传递(变量的传递都是值传递,指针也是变量,所以指针传递的时候,指针本身也是值传递),然后利用这个临时指针访问变量(需要解引用),假设指针临时变量符号是
L4 ,内存地址是 0x3473FEDA ,则示意如下:



3. 以引用为参数时,因为引用根本就不是变量,所以编译器不会创建引用的临时变量。其实质是当编译器遇到引用形参时,是直接用实参的标号来访问变量的,即直接通过
L2 来访问变量,所以同样可以修改变量的值(不需要解引用)。

以上就是对变量、指针、引用的简单总结。如有错误之处,欢迎指出~
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: