你真的搞懂了参数传递方式吗?(多图超详细)

举报
十八岁讨厌编程 发表于 2022/08/06 01:09:43 2022/08/06
【摘要】 文章目录 引入参数传递的两种方式深入理解按值调用引用数据类型的按值调用按引用调用证明:在java中总是值传递 引入 在学习编程语言的过程中,我相信大多数人都遇到或者经历过一个问题,有的时候...

引入

在学习编程语言的过程中,我相信大多数人都遇到或者经历过一个问题,有的时候你把变量传入了一个方法,经过方法内部的一顿操作之后,发现那个变量并没有发生变化。如果是这样也就算了,关键是有时候你传入的变量经过方法中的操作后它又发生了变化。这是啥情况?😂莫非每次向方法中传入参数都是一场豪赌吗?还是遇事不决量子力学,莫非是那股神奇的力量?😎好吧扯远了,回归正题,归根结底是因为你没有彻底的弄明白编程语言的参数传递过程

参数传递的两种方式

我相信大多数人都知道参数的两种传递方式:

  • 按值调用(call by value)
  • 按引用调用(call by reference)

这个针对大多数的编程语言是成立的,当然也有例外,例如:c++还有一个按指针传递(不过都可以按如上这两种理解)。
在很久很久之前还有一个按名调用(call by name)
不过大家放心,现在已经弃用(( •̀ ω •́ )✧ 虚晃一枪)

按值调用表示方法接收的是调用者提供的值。
按引用调用表示方法接收的是调用者提供的变量地址。

讲到这里有人可能会说这些我都知道,确实很多人都知道,但也只知道这些了,没有深入的理解,如此的话相当于还是没懂。

接下来上菜!🤞

深入理解按值调用

在这里我们以java语言为例

Java程序设计语言总是采用按值调用。也就是说,方法得到的是所有参数值的一个副本。 ------《Java核心技术 卷Ⅰ》

这句话说的相当的透彻,但是俺还是要提几句。什么是参数值?参数值就是你那个变量里面到底装的是个啥玩楞。怎么样够通俗吧😎。那么什么是副本?副本这个说法太高大上了,我们换个说法分身,这个知道吧,就是孙悟空用毫毛变的那个分身,分身终归是分身,它并不是本体

我们再合起来理解这句话,也就是说按值调用,就是把变量里面装的那个东西传到方法的形参,自己真身还在外面,自己的分身进到方法里去了。

现在我们来举个例子(为了各种语言使用者都能理解,以下使用我的自创语言,跳出三界之外,不在五行之中(●ˇ∀ˇ●)):

方法A(形参){把传进来的数加个2} //定义方法A
a = 2
方法A(a)  //把a传进方法A

  
 
  • 1
  • 2
  • 3

a这个变量里面装的就是2,他把自己的2复制(分身),传到了方法中(可以说给了形参),这个方法是对他这个分身做出一系列操作,随着方法的执行结束,他的分身也就被五马分尸直接拜拜了,跟他的本体没有啥关系。

来张图解析一下:
在这里插入图片描述

我们都知道对于基本数据类型,变量里面装的是一个具体的结果;而对于引用数据类型,变量里面装的是地址。有些人错误的认为只要是传了个引用数据进方法,那就是按引用调用的参数传递方式。大错特错🤦‍♂️,接下来我们就看一下对于引用数据类型的值传递

引用数据类型的按值调用

还是用我自创的语言,为大家举个例子:

方法A(形参x){对传入的对象的属性进行改动}
a = 某类的对象
方法A(a)

  
 
  • 1
  • 2
  • 3

还记得我们的方法论吗?

按值调用,就是把变量里面装的那个东西传到方法的形参,自己真身还在外面,自己的分身进到方法里去了。

同样的我们也按照上面的方法进行理解。a变量的里面装的是对象的地址,然后a把这个地址复制一份给了形参x,这个分身进入方法中完成属性的改动。

如此一套猛如虎的操作进行下来,一看最后结果傻了眼。不是说进去的是分身,怎么a的属性变了?因为当a把自己的地址给了形参x之后,形参x也拥有了一个指向对象的指针,有了这条指针,当然可以进行改动!

看图!(〃 ̄︶ ̄)人( ̄︶ ̄〃):
在这里插入图片描述
纵使形参x在方法执行完毕之后会被回收,但是a指向的对象还在,他造成的影响也还在。

按引用调用

按引用调用,很多人第一反应,就是传地址,这没错,但是关键点在于传什么的地址。很多人不明白按引用调用的本质,就是因为这个地方没搞明白。

给你举个例子:
现在有一个变量a,里面装着某个对象的地址
在这里插入图片描述
将变量a传入方法,倘若是按引用调用,传地址,传哪个?这就是引用调用的核心!

按引用调用表示方法接收的是调用者提供的变量地址。

也就是说给形参的是那个0x1122的地址,而这个0x1122就是变量a在内存中的地址值,换句话说按引用调用相当于直接把真身放到方法中去,这回是孙悟空亲自出山,而不是他的分身了!(~ ̄(OO) ̄)ブ

还没有完全搞懂?没事👌,接下来我们通过一个证明来加深理解!

证明:在java中总是值传递

此实验参考《Java编程思想》

首先我们编写一个交换两个Employee对象的方法:

public static void swap(Employee x,Employee y){
	Employee temp = x;
	x = y;
	y = temp;
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

如果Java对对象采用的是按引用调用,那么这个方法就应该实现交换:

var a = new Employee{"Alice",·····}var b = new Employee{"Bob",······}
swap(a,b);

  
 
  • 1
  • 2
  • 3

但是最终失败了,两者没有发生交换。

我们可以看看两种情况的内存解析图:

如果是按值调用:
在这里插入图片描述

可以看到任x、y如何乱搞,a、b都纹丝不动,所以最后的结果出来,两者是没有交换的。

如果是按引用调用:
在这里插入图片描述
可以看到如果真是按引用调用,那么两者是可以交换的。

文章来源: blog.csdn.net,作者:十八岁讨厌编程,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/zyb18507175502/article/details/122821770

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。