总结:Ruby里是值传递还是引用传递

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了总结:Ruby里是值传递还是引用传递相关的知识,希望对你有一定的参考价值。

在ruby中一切都是对象,而你向方法中传递的实质上是对象的引用( object-reference)。ruby中变量都是对象的引用。

先来看

def pref2(agr)
agr.downcase
end


a2 = ‘PREF2‘
pref2(a2)
puts "#{a2}" #输出 PREF2

为什么调用了pref2后 a2还是大写的“PREF2”,看一下downcase的源码就不难发现问题了。

链接:https://ruby-doc.org/core-2.4.1/String.html,搜索downcase

 

看到str=rb_str_dup(str); 这句其实真相大白了,实际上dwoncase返回的是一个新的字符串,并不是你原来传进去的字符串对象的引用了。
所以经过了pref2方法后,a2的值并没有发生改变。

 

再来看

def pref1(agr) 
agr.downcase!
end

a1 = ‘HELLO‘
pref1(a1)
puts "#{a1}" #输出 hello

为什么经过了pref1方法a1的值发生了变化。还是先来看看downcase!的源码

链接:https://ruby-doc.org/core-2.4.1/String.html,搜索downcase!

 

查看源码后发现传入的对象引用自始至终未被更改过,所以最终返回的还是a1的引用,所以a1对象的内容在dwoncase!方法中被改变了。
 
接下来继续看看
def pref3(a,b)
a,b = b,a
end

a,b = 1,2
pref3(a,b)
puts a,b #输出 1,2

为什么明明在pref3中交换了a,b结果为什么没变呢?这个问题确实比较难懂。我们可以把你的例子转换为一个更好理解的例子

 

变为

def pref3(a)
 a = 5
end

a =1
pref3(a)
puts a #输出 1

明明把a传进去了,并给它赋值为5,为什么还是1呢?我们很自然的可以想到是不是外面的a和方法中的a不是同一个东西。为了验证,我们进一步改造我们的方法

 

改造

def pref3(a)
a = 5
a.object_id
end

a =1
a.object_id #输出3

pref3(a) #输出11
puts a

 

我们发现两个a的object_id不同,他们不是一个对象,而是两个。

 现在我们明白了问题的关键,方法中的本地变量a指向了对象5,而外部的a仍旧指向的是对象1.

 

 至此整个过程我们可以理解为:

  1.  有一个对象1,我们用a保存了他的引用。
  2.  然后我们将它的“引用的拷贝”传递给了方法pref3中的本地变量a,这时本地变量a保存了1对象的引用。
  3.  我们在pref3方法中创建了5对象,将其引用赋值给了本地变量a,这时a擦去了保存的1对象的引用,而改为保存5对象的引用
  4.  调用完pref3方法 ,其本地变量a随之消亡,对象5因为没有引用而随后被垃圾回收。
  5.  而外部的变量a自始至终保存着对象1的引用。

 

现在回头想想你的方法中传进去的a,b虽然交换了位置,但是对外部定义的a,b没有丝毫影响。因为他们根本保存的就是不同的对象的引用。

ruby传递的是 引用的拷贝 并不是引用的本身。(其实就可以理解为值传递)
但对于基本类型是直接传递对象本身的。举个例子:
可以参考这个http://www.ruby-doc.org/core-1.9/classes/Fixnum.html
写道

 

“Fixnum objects have immediate value. This means that when they are assigned or passed as parameters, the actual object is passed, rather than a reference to that object. Assignment does not alias Fixnum objects. There is effectively only one Fixnum object instance for any given integer value, so, for example, you cannot add a singleton method to a Fixnum.“.

 

我觉得这篇文章能够结束这个话题了:http://www.khelll.com/blog/ruby/c-passes-by-reference-java-and-ruby-dont/

更有趣的讨论过程:http://www.khelll.com/blog/ruby/ruby-pass-by-value-or-by-reference/
 
 
收集整理自:http://www.iteye.com/topic/1117575 作者:洛克刘大神  万分感谢~~







以上是关于总结:Ruby里是值传递还是引用传递的主要内容,如果未能解决你的问题,请参考以下文章

python的参数传递是值传递还是引用传递?都不是!

java是值传递还是引用传递?

JVM_Java到底是值传递还是引用传递

PHP对象到底是值传递还是引用传递

Java是值传递还是引用传递?

Java调用函数传递参数到底是值传递还是引用传递