总结: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 作者:洛克刘大神  万分感谢~~

时间: 2024-10-12 08:34:32

总结:Ruby里是值传递还是引用传递的相关文章

JavaScript的值传递和引用传递

本文和大家分享的主要是javascript中值传递和引用传递相关内容,一起来看看吧,希望对大家学习javascript有所帮助. JavaScript有5种基本的数据类型,分别是:布尔.null.undefined.String和Number.这些基本类型在赋值的时候是通过值传递的方式.值得注意的是还有另外三种类型: Array.Function和Object,它们通过引用来传递.从底层技术上看,它们三都是对象. 基本数据类型 如果一个基本的数据类型绑定到某个变量,我们可以认为该变量包含这个基本

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

看到一个java面试题: 问:当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?  答:是值传递.Java 编程语言只有值传递参数.当一个对象实例作为一个参数被传递到方法中时,参数的值就是该对象的引用一个副本.指向同一个对象,对象的内容可以在被调用的方法中改变,但对象的引用(不是引用的副本)是永远不会改变的. 以下是从其他文章里转的,只为加深理解 public class TempTest { private void te

Java中,函数参数的传递,是值传递还是引用传递

当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?  答:是值传递. 可以这么理解:有一个Person(name="S"),作为参数传给一个方法,在此方法中将此Person重新设置name=“B”,那么有一下结论 ①这个Person还是这个Person,一直都是他,但是他的名字被改了,不管是原来的引用还是方法里的引用,引用的都是一个对象,所以,所有引用的值都变了 ②如果在方法中重新new了一个Person赋给参数,

Java中的值传递与“引用传递”

首先,Java没有 引用传递 这么一说. Java只有值传递,传递的都是值,基本数据类型传递的是值,引用类型传递的是地址值. 我来理一下这其中犹如米线跟米面绞在一起了,再跟粉丝混在一起的关系. 好的,我们来看第一个例子: public static void main(String[] args) { int a = 1; int b = 4; System.out.println("Before : a=" + a + "," + "b=" +

java 中值传递和引用传递(转)

java中给函数传递参数的方式有两种:值传递和引用传递.一般而言,基本类型是值传递:引用类型是引用传递.但传值时到达发生了什么? 1.基本类型 8个基本类型(byte,short,int,long,float,double,char,boolean)是值传递. 1 public class ValueTest { 2 3 public static void main(String[] args) { 4 int a = 10; 5 changeVal(a); 6 System.out.prin

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

一.Java中什么叫做引用类型变量? 引用:就是按内存地址查询       比如:String s = new String();这个其实是在栈内存里分配一块内存空间为s,在堆内存里 new了一个String类型的空间,在运行时是 栈内存里的 s 指向堆内存里的那一块存储空间 基本数据类类型存的是数值本身,而引用类型变量在内存放的是数据的引用,并不是数据的本身, 引用类型变量是以间接方式去获取数据. 引用类型变量都属于对象类型,如:数组.类.字符串等都属于引用类型变量.所以,引用类型 变量里面存

Java中对象、对象引用、堆、栈、值传递以及引用传递的详细解释

Java中对象.对象引用.堆.栈.值传递以及引用传递的详细解释 1.对象和对象引用的区别: (1).对象: 万物皆对象.对象是类的实例.在Java中new是用来在堆上创建对象用的.一个对象可以被多个引用所指向. (2).对象引用: 类似于C++中的地址.通过对象引用可以找到对象.一个引用可以指向多个对象.操纵的标识符实际上是指向对象的引用. 就像:对象存放在屋子里,对象的引用就相当于屋子的钥匙. 2.值传递和引用传递的区别: (1).值传递:传递的是值的拷贝.也就是说传递后就不互相关了. (2)

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

Java面向对象-方法的值传递和引用传递 方法的值传递: 值传递 在方法里改变变量的值 作用范围仅仅是方法里 对外面不影响: 上代码: 1 package com.java1234.chap03.sec03; 2 3 public class Person { 4 5 void speak(int age){ 6 System.out.println("我今年"+age+"岁了"); 7 age=24; // 作用范围是方法里 8 } 9 10 public sta

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

tips:这篇文章是听了四脚猫的js课程后查的,深入的理解可以参看两篇博客: JavaScript数据类型--值类型和引用类型 JavaScript数据操作--原始值和引用值的操作本质 在传统的观念里,都认为JavaScript函数传递的是引用传递(也称之为指针传递),也有人认为是值传递和引用传递都具备.那么JS的参数传递到底是怎么回事呢?事实上以下的演示也完全可以用于Java 首先来一个比较简单的,基本类型的传递: function add(num){ num+=10; return num;

java 传参方式--值传递还是引用传递

java 传参方式--值传递还是引用传递 参数是按值而不是按引用传递的说明 Java 应用程序有且仅有的一种参数传递机制,即按值传递.写它是为了揭穿普遍存在的一种神话,即认为 Java 应用程序按引用传递参数,以避免因依赖“按引用传递”这一行为而导致的常见编程错误. 对此节选的某些反馈意见认为,我把这一问题搞糊涂了,或者将它完全搞错了.许多不同意我的读者用 C++ 语言作为例子.因此,在此栏目中我将使用 C++ 和 Java 应用程序进一步阐明一些事实. 要点 读完所有的评论以后,问题终于明白了