新手问题 Ruby 中关于二维数组直接赋值的问题

keyv2 · 发布于 2017年5月09日 · 最后由 keyv2 回复于 2017年5月16日 · 476 次阅读
E114e4

定义一个二维数组ary,我先是给 ary[0][0]赋值为 1,再是给 ary[1][0]赋值为 233,结果输出 ary[0][0] 居然为 233,输出整个ary ,发现每个数组第一项都是 233

截图

本人是一名大二学生……就看过那本巨红的ruby基础教程,这个问题实在是难到我了……

所以想请问这到底是什么原因?如果我定义一个二维数组,并初始化两个值具体又应该怎么做?

共收到 9 条回复
96

你这数组第一维的每一个子数组都是同一个指针引用。试试 Array.new 的时候传个 block 进去吧

E114e4
32qinix 回复

多谢,将后一个Array.new通过块传入的确可以实现我的目的。 但这样定义的时候默认采取引用的方式又有什么好处呢……不是很理解这种机制的目的

4215
E114e4keyv2 回复

文档说默认定义是适合于不可变的,比如数字。这种默认写法比较简洁,新手确实容易困惑。需要看文档。

建议学Elixir语言,估计就没有这类的困惑了。

E114e4
4215chenge 回复

非常感谢,看来如果要深入学习ruby不看文档是不行的

另一方面,Elixir的话,考虑到现在大二,明年打算去找实习,所以我还是想把更多时间放在基础上。

23529

只要记住ruby里传递的永远是引用就好了,包括数字传的也是引用,不提供代码块,只提供一个对象引用的话,这个对象不一定是可复制的(虽然数组可以),所以Array.new肯定不会帮你复制

E114e4
23529mizuhashi 回复

惊了,今天下午上课自己想了一下,然后查了一下相关资料,发现所有传递引用的说法完全可以解释并且行得通。

因为Array.new(6,[])的时候,我传递的是一个数组引用,每一维都指向同一个引用,那么我在这个被引用的数组作修改,的确会影响到其他维数的数组。
而传递block的时候,应该是6次Array.new的时候都重新执行一次Array.new,那么每一维都指向不同的new出来的数组引用。

而大佬你说的数字传递的也是引用问题,我在这里得到了充分解释,并且在我的理解范围内是正确的。

在赋值的时候,ruby根据右值创建对象并返回该对象的引用,并不论左值是否为空,原引用对象是什么,都会将之覆盖。这种不论左值都可赋值也正是任何变量都是引用的体现是么!!!!

也许我现在才有一点点理解了动态语言,想想有点小激动……

另外的,如果以上成立,那么在ruby中,我们创建对象的时候返回引用,因此只能通过引用间接访问。如果一个创建的对象之后我可能不需要了,那么它只能留在那里,我们无法自主删除。然而某些对象比如数字和字符串中会用的比较频繁,那会不会引起一些内存问题呀…………

E114e4
23529mizuhashi 回复

哦,我想起来了,我在ruby基础教程看到过,ruby会对每个对象引用进行计数,如果计数个数变为0就会自动释放。完美!

23529
E114e4keyv2 回复

惊了可还行,怕不是真实猛男(滑稽

不过ruby用的不是引用计数,是mark and sweep: http://blog.jobbole.com/60900/

E114e4
23529mizuhashi 回复

煞笔了煞笔了,我居然自以为这个问题已经被我完美解决了……今天回来逛逛意外的发现完全受教了。真的是非常感谢。

E114e4 keyv2 关闭了讨论 5月16日 17:19
E114e4 keyv2 重新开启了讨论 5月16日 17:19
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册