论坛首页 编程语言技术论坛

ruby 函数到底是按值传递还是按引用

浏览 18717 次
精华帖 (0) :: 良好帖 (1) :: 新手帖 (3) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-11-07  

例子:

 

def pref1(agr)   
   agr.downcase!
end

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


def pref2(agr)
    agr.downcase
end


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


def pref3(a,b)
    a,b = b,a
end

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


def pref4(agr)
    agr.replace('aaaaa')
end

a4 = 'a'
pref4(a4)
puts a4 #输出 aaaaa

 

 

 

ruby 函数到底是按值传递还是按引用???

 

   发表时间:2011-11-08  

ruby中没有什么值传递和引用传递的概念。在ruby中一切都是对象,而你向方法中传递的实质上是对象的引用( object-reference)。ruby中变量都是对象的引用。

 

先来看

 

def pref2(agr)
agr.downcase
end


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

 

为什么调用了pref2后 a2还是大写的“PREF2”,看一下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!的源码


 

查看源码后发现传入的对象引用自始至终未被更改过,所以最终返回的还是a1的引用,所以a1对象的内容在dwoncase!方法中被改变了。

 

太晚了,明日继续后两个

 

 

 

  • 大小: 11.1 KB
  • 大小: 107 KB
0 请登录后投票
   发表时间:2011-11-08  
@洛克刘

膜拜大牛~
0 请登录后投票
   发表时间:2011-11-08  
洛克刘 写道

ruby中没有什么值传递和引用传递的概念。在ruby中一切都是对象,而你向方法中传递的实质上是对象的引用( object-reference)。ruby中变量都是对象的引用。

 

先来看

 

def pref2(agr)
agr.downcase
end


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

 

为什么调用了pref2后 a2还是大写的“PREF2”,看一下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!的源码


 

查看源码后发现传入的对象引用自始至终未被更改过,所以最终返回的还是a1的引用,所以a1对象的内容在dwoncase!方法中被改变了。

 

太晚了,明日继续后两个

 

 

 

等待中。。。。。。

 

 

0 请登录后投票
   发表时间:2011-11-08   最后修改:2011-11-08

接下来继续看看

 

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没有丝毫影响。因为他们根本保存的就是不同的对象的引用。

 

 

 

 

 

 

 

0 请登录后投票
   发表时间:2011-11-08  
" 至此整个过程我们可以理解为:

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


很清析~~~

太好啦~~~  3Q~~~

恩,这貌似在python里也是一样的~~

恩,这里还一个作用域的问题~
0 请登录后投票
   发表时间:2011-11-09   最后修改:2011-11-14
ruby里全部都是指针吗? 我是来学习的。
0 请登录后投票
   发表时间:2011-11-09  
ruby是传值啊
http://advogato.org/person/fxn/diary/534.html
0 请登录后投票
   发表时间:2011-11-09   最后修改:2011-11-09
在ruby里面对象分两类,对于可以在32 bit(其实没有32bit)中存得下的值,例如Fixnum,nil,true/false等,变量里面是存值的。对于其他对象,变量里面存的是指向对象的“句柄”。
ruby函数调用传递的是“值” - 净值(对于第一类),或句柄。
0 请登录后投票
   发表时间:2011-11-09   最后修改:2011-11-09
Hooopo 写道

 

   
    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/

 

0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics