传值还是传引用—— java和C函数参数传递解读

关于Pass-By-refrence 和Pass-By-value 的争论始终活跃在论坛一线。 

今天就来揭露其中的来龙去脉, 给自己和初学者来个彻底剖析。

 

首先来看, 为什么有"值"和"引用"的提法.

 

什么是值(Value), 直接操作的东西, 就是值。如我有一个包裹, 不用通过中间手段, 我拿起来就可以操作。

相对于引用(refrence), 是指间接的东西。比如我有一个包裹的传单, 当然要通过这个传单上的包裹地址,才能找到包裹,进而去操作。

reference, 就是中介的意思,指引你去找到你需要的对象(值). reference除了帮你找到你需要的对象之外,没有其它作用。

 

在Java中, 没有“对象(值)”,之说,你看到的,都是对象的reference,并且都是在堆中创建(基本类型除外), 比如:

Object obj = new Object(); //创建一个对象(在堆中), 并将obj引用指向这个对象。

不像C++,除了上述方法之外,还可以这样创建:

Object obj(); //创建一个对象(在栈中), obj是一个实实在在的对象

因此,java中,明确表示,java中,只有引用的概念。

 

 

现在来看参数传递的原理:

 

定义一个函数 void fuction(A a)

这里A可以指代任何变量, 指针,值或者是其它。

 

调用时:

A b;

fuction(b);

发生了什么事情?

首先b将自己复制一份b1,并将b1作为形参,给fuction的入口值a.

所有的函数传递务必都是这样,但是,当形参如果reference和value的时候, 我们会有一些混淆:

1. 当为value传递的时候, 实参会复制一份, 比如用值的传了一个包裹到fuction中, 这个时候,包裹被复制, 所以包裹不是原来的包裹,此时,改写包裹内容, 对原来的包裹没有任何作用了!

 

2. 当为reference传递的时候,如前所述,此时传递的是带有包裹地址的传单, 这个时候传单复制了一份, 相当于复印件。 我们的操作,都是通过复印件传单的地址,去找到包裹,然后操作。复印件上的地址,和原来的地址,肯定是一样的,所以,我们找的,依然是原来的包裹对象,改写包裹,当然会对原来的包裹产生影响。

 

所以,函数传参, 都是值,引用值或者对象值 。如果想修改对象,传引用进去,这样方便找到对象然后去修改。

 

 

为什么要复制一份呢! 原因是每个函数是一个栈结构,栈空间管理变量资源,所以就有复制一说。

鉴于复制的原因,所以,传参数的时候,还是传引用比较好,大的对象会非常消耗栈空间的。

 

 

前些天论坛有个有趣的例子: 抄摘过来:

 

 

结果是这样的:

 

结果为:
first : hello
second: hello world
third :
main  : hello world

 

把我的回复粘贴一把:

 

 

举一个例子:

有人从邮局给你送了一个包裹(对象new StringBuffer("hello")), 然后通过一个凭据(StringBuffer  str1)写明包裹所在的邮局地址(包裹的引用地址),同时将这个凭据复印了一下(StringBuffer str),  , 让你操作一下(test函数),撕开包裹,取出邮件。

重点讲一下test函数,即你拿到凭据复印件str之后,怎么操作的,

你通过str到地址邮局中找到了包裹, 打开它,在里面塞了一些废纸,
然后,你自己又弄了一个新包裹, 在里面塞了一只烟灰缸。这个时候,你把地址的复印单改成了新包裹的地址。

 

于是最后结果: 你原来的包裹, 里面有废纸,

 

新的包裹,里面有烟灰缸;

 

但很糟糕的是, 你私自改了包裹的复印单(生活中,复印单一般是不允许更改的,更改就无效),把它改成你新包裹的地址,

 

但你没有返回这个改了的复印单,你把它遗忘了, 所以处理完包裹之后,带有烟灰缸的包裹地址,你找不到了!

 

最后,你只能拥有原来的包裹,因为原来的包裹地址(包裹的地址的原件)邮局还为你保留着呢!

 

顺便提及,这里如果想得到带有烟灰缸的新包裹, 给一个返回值就OK了; 但似乎这并不是一个好的解决方案。

 

为了防止改写复印件, c++传递指针的时候, 用了关键词Constant, java则用了final,

 

异曲同工.

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值