在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里是值传递还是引用传递的更多相关文章

  1. Java中引用类型变量,对象,值类型,值传递,引用传递 区别与定义

    一.Java中什么叫做引用类型变量?引用:就是按内存地址查询       比如:String s = new String();这个其实是在栈内存里分配一块内存空间为s,在堆内存里new了一个Stri ...

  2. java中值传递和引用传递

    最近工作中使用到了值传递和引用传递,但是有点懵,现在看了下面的文章后清晰多了.一下是文章(网摘) 1:按值传递是什么 指的是在方法调用时,传递的参数是按值的拷贝传递.示例如下: public clas ...

  3. Java中的值传递和引用传递

    这几天一直再纠结这个问题,今天看了这篇文章有点思路了,这跟C++里函数参数为引用.指针还是有很大区别. 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里 ...

  4. JavaScript 函数参数传递到底是值传递还是引用传递

    tips:这篇文章是听了四脚猫的js课程后查的,深入的理解可以参看两篇博客: JavaScript数据类型--值类型和引用类型 JavaScript数据操作--原始值和引用值的操作本质 在传统的观念里 ...

  5. java中方法的参数传递机制(值传递还是引用传递)

    看到一个java面试题: 问:当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?  答:是值传递.Java 编程语言只有值传递参 ...

  6. java参数传递时到底是值传递还是引用传递

    java参数传递时到底是值传递还是引用传递(baidu搜集) 问”,很多人的BLOG里都引用这些面试题,最近因为工作内容比较枯燥,也来看看这些试题以调节一下口味,其中有一道题让我很费解. 原题是:当一 ...

  7. Java面向对象-方法的值传递和引用传递

    Java面向对象-方法的值传递和引用传递 0 发布时间:『 2016-08-21 14:21』  博客类别:Java核心基础  阅读(197) 评论(0) Java面向对象-方法的值传递和引用传递 方 ...

  8. String是值传递还是引用传递

    String是值传递还是引用传递 今天上班时,同事发现了一个比较有意思的问题.他把一个String类型的参数传入方法,并在方法内改变了引用的值. 然后他在方法外使用这个值,发现这个String还是之前 ...

  9. 堆栈详解 + 彻底理解Java的值传递和引用传递

    本文旨在用最通俗的语言讲述最枯燥的基本知识 学过Java基础的人都知道:值传递和引用传递是初次接触Java时的一个难点,有时候记得了语法却记不得怎么实际运用,有时候会的了运用却解释不出原理,而且坊间讨 ...

  10. JAVA不可变类与可变类、值传递与引用传递深入理解

    一个由try...catch...finally引出的思考,在前面已经初步了解过不可变与可变.值传递与引用传递,在这里再次深入理解. 1.先看下面一个try..catch..finally的例子: P ...

随机推荐

  1. hdu 3549 最大流

    #include<stdio.h> #include<string.h> #include<queue> #include<iostream> usin ...

  2. vs2005添加include lib文件目录

    vs2005添加include lib文件目录 http://blog.sina.com.cn/s/blog_79489160010145wb.html 1. 添加编译所需要的 lib 文件 [解决方 ...

  3. TSP服务商

    1.何为TSP? TSP([1] Service Provider),在Telematics产业链居于核心地位,上接汽车.车载设备制造商.网络运营商,下接内容提供商.谁掌控了TSP,谁就能掌握Tele ...

  4. CentOS6.5下修改MySQL编码方法

    1.查看默认编译,默认登陆到mysql后,通过show variable like命令来查看系统变量 可以看到,默认的数据库编码方式基本设置成了latin1的编译方式,此时我们需要将其修改成utf8的 ...

  5. M - Substrings

    You are given a number of case-sensitive strings of alphabetic characters, find the largest string X ...

  6. P​H​P​中​h​t​t​p​协​议​详​解

    对PHP文件来说 Php能够有  html   css javascript php脚本 flash它的不同部分是在不同的地方运行的(server和client) http协议 1. http协议是建 ...

  7. Wscript对象具体解释

    15.6  Windows脚本宿主的内建对象 每一个编程环境都提供了自己的对象模型,开发者 能够使用这些对象模型实现各种解决方式,WSH也不例外.WSH包括了一组核心对象,分别包括了属性和方法,能够用 ...

  8. double型转换成string型

    double型转换成string型 题目描写叙述: 如有一个函数.其可接受一个long double參数,并将參数转换为字符串.结果字符串应保留两位小数,比如,浮点值123.45678应该生成&quo ...

  9. rnnlm源代码分析(八)

    系列前言 參考文献: RNNLM - Recurrent Neural Network  Language Modeling Toolkit(点此阅读) Recurrent neural networ ...

  10. ant+jmeter 报告优化

    环境基础:ant+jmeter+java +jmeter脚本 1.将 JMeter的extras目录中ant-jmeter-1.1.1.jar包拷贝至ant安装目录下的lib目录中 2.修改JMete ...