def add(a,b) a = a.push(b) end x = [1] y = 2 add(x, y)之后,x变成了 [1,2]
可是
def add(a,b) a = a + b end x = 1 y = 2 add(x, y)之后, x还是1
这是为什么?一个参数进行了复制,一个是指针?? 这要如何判断传递方式呢?
可以区分简单数值和复杂容器对象吧,比如数组和散列。可以用 clone 来避免这种情况吧: a.clone.push b
a.clone.push b
#1 楼 @chenge 如何避免到好说,问题是这里面的规则是什么? 什么时候是复制,什么时候是指针?
参数都是对象的引用,只是Array#push方法将调用数组修改了
楼主可以看看这两篇 Variable References and Mutability of Ruby Object,Object Passing in Ruby - Pass by Reference or Pass by Value
#4 楼 @shallmentmo 看来还是个复杂的问题。我看了那个英文解释,似乎也没看懂,说是第三种,引用值传递。
简单来说,可以认为是引用传递,数值除外。
首先要知道变量和变量指向的对象是不一样的,就像叫 Shakespeare 的人是一个人,而 Shakespeare 只是一个名字。ruby 是传值的,但传的值是变量的拷贝,而不是变量指向的对象的拷贝,也就是说函数体里面的 a(称之为 a`)跟 外面的 a 是完全不同的两个变量,只是它们指向了内存里的同一个对象,
例子 1 中使用了 push,a` 指向的对象发生了改变,而 a 跟 a` 指向的是相同的对象,所以就发生变化啦
例子 2 中对 a` 进行了重新的赋值,这个时候 a` 已经完全指向了一个新的地址,已经跟外面的 a 没有任何关系了,a 指向的对象并没有发生变化
参考 http://robertheaton.com/2014/07/22/is-ruby-pass-by-reference-or-pass-by-value/
我的两个理解点 1,ruby 是浅拷备的 2,代码解释由右至左
a.push 的方法,基于浅拷备,不另辟内存空间,所以改变的是原值
add function 里面 a 是一个新变量会有一个新的 object_id,它只是指向 function 外面的 a 的地址,在 a = a 的过程只,只是声明了一个新的 object,并没有开辟内存空间去存值 a = a + b 先计算 a+b,然后指向新的内存地址
估计是为了省内存吧 乱猜的
@chenge 我的理解是都是引用传递,只是第一个 def add(a, b); a.push(b); end 这里面不用 a= ,push 方法是会改变 a 指向的对象(同是也是 x 指向的对象),第二个的话,只是改变了 a 的指向,并没有改变 a 指向的 object。
def add(a, b); a.push(b); end
a=
这段代码里改变 a 值的是 a.push(b), 至于后面的 a = 这段,符号是有作用域的。你在函数传参时只传递了引用,并没有将外层的符号传递进来,里面的 a 和外面的 x 并不是同一个符号,只是它们指向相同的对象。你在函数中对符号 a 这个所指向的引用进行了改变,并不会影响原来 a 所指向的对象. 所以第二段也不会影响 x, 因为 a + b 这个操作是不会影响 a 原来所指对象的值的
谢谢大家。大概懂了。