新手问题 函数参数疑问

zix · 2016年08月20日 · 最后由 zix 回复于 2016年08月20日 · 2415 次阅读
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

#1 楼 @chenge 如何避免到好说,问题是这里面的规则是什么? 什么时候是复制,什么时候是指针?

参数都是对象的引用,只是 Array#push 方法将调用数组修改了

#4 楼 @shallmentmo 看来还是个复杂的问题。我看了那个英文解释,似乎也没看懂,说是第三种,引用值传递。

简单来说,可以认为是引用传递,数值除外。

6楼 已删除

首先要知道变量和变量指向的对象是不一样的,就像叫 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 = a.push(b)
end

x = [1]
y = 2
add(x, y)之后,x变成了
[1,2]

这段代码里改变 a 值的是 a.push(b), 至于后面的 a = 这段, 符号是有作用域的. 你在函数传参时只传递了引用, 并没有将外层的符号传递进来, 里面的 a 和外面的 x 并不是同一个符号, 只是它们指向相同的对象. 你在函数中对符号 a 这个所指向的引用进行了改变, 并不会影响原来 a 所指向的对象. 所以第二段也不会影响 x, 因为 a + b 这个操作是不会影响 a 原来所指对象的值的

谢谢大家。大概懂了。

huacnlee 关闭了讨论 08月22日 15:08
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册