引用和指针的区别都有什么_c++中,引用和指针的区别是什么?

c7aff393e1793ca4e2dbc1ff8c9be8e6.png

什么是指针pointer,什么是引用reference?它们的区别是什么?有什么共性吗?补充:什么时候使用pointer比较好,什么时候用reference? 用pointer和不用有什么区别影响吗?

引用是C++引入的重要机制(C语言没有引用),它使原来在C中必须用指针来实现的功能有了另一种实现的选择,在书写形式上更为简洁。那么引用的本质是什么,它与指针又有什么关系呢?

1.引用的底层实现方式

引用被称为变量的别名,它不能脱离被引用对象独立存在,这是在高级语言层面的概念和理解,并未解释引用的实现方式。常见错误说法是“引用”自身不是一个变量,甚至编译器可以不以引用分配空间。

实际上,引用本身是一个变量,只不过这个变量的定义和使用与普通变量有显著的不同。为了解引用变量底层实现机制,考查如下代码:

int i=5;int &ri=i;ri=8;

在Visual Studio 2017环境的debug模式调试代码,反汇编查看源码对应的汇编代码的步骤是:调试->窗口->反汇编,即可得到如下原码对应的汇编代码:

int i=5;00A013DE  mov        dword ptr [i],5    //将文字常量5送入变量iint &ri=i;00A013E5  lea        eax,[i]       //将变量i的地址送入寄存器eax00A013E8  mov        dword ptr [ri],eax  //将寄存器的内容(也就是变量i的地址)送入变量riri=8;00A013EB  mov        eax,dword ptr [ri]  //将变量ri的值送入寄存器eax00A013EE  mov        dword ptr [eax],8   //将数值8送入以eax的内容为地址的单元中return 0;00A013F4  xor        eax,eax

考查以上代码,在汇编代码中,ri的数据类型为dword,也就是说,ri要在内存中占据4个字节的位置。所以,ri的确是一个变量,它存放的是被引用对象的地址。由于通常情况下,地址是由指针变量存放的,那么,指针变量和引用变量有什么区别呢?使用指针常量实现上面的代码功能。考查如下代码:

int i=5;int* const pi=&i;*pi=8;

按照相同的方式,在VS2017中得都如下汇编代码:

int i=5;011F13DE  mov         dword ptr [i],5  int * const pi=&i;011F13E5  lea         eax,[i]  011F13E8  mov         dword ptr [pi],eax  *pi=8;011F13EB  mov         eax,dword ptr [pi]  011F13EE  mov         dword ptr [eax],8  

观察以上代码可以看出:

(1)除了pi与ri变量名不同,所得汇编代码与第一段所对应的汇编代码完全一样。所以,引用变量在功能上等于一个指针常量,即一旦指向某一个单元就不能在指向别处。

(2)在底层,引用变量由指针按照指针常量的方式实现。

2.高级语言层面引用与指针常量的关系

1.引用和指针,在内存中都是占用4个字节(32bits系统中)的存储空间。指针和引用存放的都是被引用对象的地址,都必须在定义的同时进行初始化。

2.指针常量本身(以p为例)允许寻址,即&p返回指针常量(常变量)本身的地址,被引用对象用*p表示;引用变量本身(以r为例)不允许寻址,&r返回的是被引用对象的地址,而不是变量r的地址(r的地址由编译器掌握,程序员无法直接对它进行存取),被引用对象直接用r表示。

3.凡是使用了引用变量的代码,都可以转换成使用指针常量的对应形式的代码,只不过书写形式上要繁琐一些。反过来,由于对引用变量使用方式上的限制,使用指针常量能够实现的功能,却不一定能够用引用来实现。

例如,下面的代码是合法的:

int i=5,j=6;int* const array[]={&i,&j};

而如下代码是非法的:

int i=5,j=6;int& array[]={i,j};

也就是说,数组元素允许是指针常量,却不允许是引用。C++语言机制如此规定,原因是避免C++语法变得过于晦涩。假如定义一个“引用的数组”,那么array[0]=8;这条语句该如何理解?是将数组元素array[0]本身的值变成8呢,还是将array[0]所引用的对象的值变成8呢?对于程序员来说,这种解释上的二义性对正确编程是一种严重的威胁,毕竟程序员在编写程序的时候,不可能每次使用数组时都要回过头去检查数组的原始定义。

即得出两个不同:引用只能在定义时被初始化一次,之后不可变,但是指针可变;引用没有 const,指针有 const。

4.一些其他不同:

引用使用时无需解引用(*),指针需要解引用;

“sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身(所指向的变量或对象的地址)的大小;

引用不能为空,指针可以为空;

指针和引用的自增(++)运算意义不一样;引用自增被引用对象的值,指针自增内存地址。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值