从汇编和高级语言的角度理解传值方式,传值,传引用,传指针的本质机制与区别。白话通俗易懂。

函数的传参与返回值的方式有传值和传递引用,c语言中就是传值,而c++扩展传引用。

而传值分为传递值(实参的值,此时形参是实参在内存中的一份拷贝,形参在使用时分配内存,结束时释放,实参和形参在内存中的地址不同,因此对形参的改变不会改变实参)

传值的另外一种是传指针(传递的值是实参的地址,此时形参的值为实参的地址,所以对形参的修改就会修改实参的值)

而传引用,从高级语言的层面看,引用是实参的别名,所以对形参的修改就是直接对实参的改变。引用是变量的地址,可以理解为一个常指针,也就是指向固定的指针,但是与指针还是有区别的,具体使用的时候不同,并且引用于指针有很多不同,引用必须初始化,但是指针可以定义的时候不初始化,另外指针可以指向空NULL,这一方面引用比指针更安全,但是引用还是存在风险的只是风险小一点而已。比如,引用一个不合法的地址。举例:

int *e=newint(10);
int &f=*e;

delete e;
f=30;

从汇编底层代码的层面看,如果将函数传参的传指针和传引用的方式的函数分别生成汇编代码发现,是一模一样的,主调函数的传参的汇编代码也是一模一样的,所以从底层汇编代码看,传引用就是通过传指针实现的。汇编代码都是通过lea取地址和mov把取到的地址放到一块内存中。


还有一个问题是,引用的本质是什么,引用到底占不占内存?

主要是针对很多关于引用的说法上,比如引用是别名,不是值不占内存,只有声明没有定义。

其实这些说法是不准确的,没有从深层上去分析,只是表面上看到的现象说法。确切说是编译器给你做的优化的表象。因为从底层汇编实现代码上看,引用和指针完全一样,根本的区别就在编译器处理的环节,很多限定都是在编译时限制的,比如引用是指针指向固定的指针,这个定向就是在编译环节限定的,像const和private等一样,在汇编代码中并没有相应的代码,都是在编译器处理的时候做相关的限定的。

int a =10;

int *p=&a;

int &q=a;

指针p,每次都要先到指针p自身的地址把p的内容(p的内容是p指向的内容的地址&a)取到,然后再到取到的地址&a中把内容10取出来,也就是先寻址后取值。而编译器对引用q做了优化,每次碰到引用q就相当于*p,不用先去p里面取地址,直接就是相当于a,对所有q的操作都相于是对*p的操作也就是对a的操作,所以对q取地址,就是对a取地址,也就是&q=&a。(所以当利用sizeof对指针p,是指针本身的所占字节数,也就是地址&a的存放的字节数,而sizeofq的时候,因为q相当于a或者相当于*p,就是10所占的字节数。也就是说所有对实际引用q的操作都会被编译器转化为a的操作,不会得到实际的q的操作;另外指针和引用的自增++操作得到的结果也不同,指针自增p++,指向变化了,而引用的++相当于(*p)++,相当于a++。这个是是说明了指针本身的值(所指向的地址)是以传值的方式传递的,改变本

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值