我期待得到:
array # => [[1, 0], [2, 0]]
如果我运行以下代码:
array = []
position = [0, 0]
2.times do
position[0] += 1
array << position
end
我明白了:
array # => [[2, 0], [2, 0]]
有人可以解释一下这里发生了什么吗?
答案 0 :(得分:4)
position
是一个对象。当您致电array << position
时,您真正在做的是将position
的引用添加到array
。这意味着,只要您修改position
,所有对它的引用都将反映这些更改。
要获得您期望的结果,您可以在每次传递中复制position
数组。这样,后续通行证不会改变你的结果。
array = []
position = [0, 0]
2.times do
position[0] += 1
array << position.clone
end
puts array.inspect
答案 1 :(得分:1)
这里的事情是,位置[0]首先等于[0,1]与你的陈述:
position[0] += 1
这使你看起来像是在挖掘&#39;第一次[0,1],第二次[0,2]。铲运算符的作用是它不像=
赋值。这与<<
&#39;突变调用者&#39;的概念有关。通过观察它,我发现它更容易理解:
a = "Hello!"
b = a
a << ", my friend"
puts a # a is now "Hello!, my friend"
puts b # b is now "Hello!, my friend"
<<
运算符不会重新分配a
在内存空间中指向的内容。将此与=
运算符进行对比,该运算符不会改变调用者:
a = "How about this?"
b = a # b is now "How about this?"
a = "Not anymore"
puts b # b is still "How about this?"
puts a # a is now "Now anymore"
关于使用.clone
方法的另一个好答案很重要,因为它可以执行所谓的&#34;浅拷贝&#34;,这意味着对象的实例变量被复制,但是不是他们引用的对象。这就是为什么它适用于这种情况。
希望看到铲子操作员如何工作,并且用它来改变值是改变它的所有它的引用而不仅仅是一个,并使输出在数组中完全相同。如果这没有完全合理,请在评论中告诉我。