当a = b时,Ruby不会创建b的重复变量a吗?

时间:2016-06-24 14:07:07

标签: ruby

在编写程序时,我发现了一些有趣的东西。如果我定义a = b<<b的任何更改都会反映在a中,反之亦然。

Ruby是否不会创建b的重复自治副本并将其以不同方式存储在?

如果没有,当我在主阵列上进行操作时,如何在特定时间点存储阵列的未被篡改的快照?

>> a = b = [0, 1]
=> [0, 1]
>> a
=> [0, 1]
>> b
=> [0, 1]
# so far so good
>> a << 2
=> [0, 1, 2]
>> a
=> [0, 1, 2]
>> b
=> [0, 1, 2]
# huh?! that can't be right, lemme try this the other way around
>>  b << 3
=> [0, 1, 2, 3]
>> a
=> [0, 1, 2, 3]
>> b
=> [0, 1, 2, 3]
# what is going on here?!

3 个答案:

答案 0 :(得分:3)

使用Object#dup

NB 它确实创建了一个浅拷贝;要创建一个深层副本,需要自己实现该副本。

▶ b = [0, 1]
#⇒ [ 0, 1 ]
▶ a = b.dup
#⇒ [ 0, 1 ]
▶ b << 2
#⇒ [ 0, 1, 2 ]
▶ a
#⇒ [ 0, 1 ]

要制作冻结和污染的副本,请使用Object#clone

答案 1 :(得分:1)

ab指向内存中的同一个对象。如果你想要一个对象的副本而不影响你可以做的原始对象

b = a.dup

答案 2 :(得分:0)

让我试着澄清这里到底发生了什么。这是引用的基本概念,由许多语言实现。当您创建“数组”时,该数组值是匿名内存对象,并且在您的代码中,ab都引用相同的对象。该语言使用“引用计数”的一些变体来跟踪存在多少引用,以便知道值何时被“孤立”并且可以被垃圾收集。

这种所谓的“浅层复制”非常有效,而且往往正是所需要的。所以,这是默认情况下这些语言的作用。

当您创建“深层复制”时,您有意识地复制匿名内存对象。现在,a指向一个,b指向另一个对象(在那个时刻)是第一个对象的快照。相比之下,这是一个耗时的过程,当然,它会分配更多的内存。现在,对一个数组所做的更改(当然)不会反映在另一个数组中,因为它们现在是两个完全不同的东西。由于这是一个不那么常见的事情,因此该语言提供了一些明确的方式来指定您想要这样做。

Ruby ... PHP ... Perl ......几乎每个人都做这样的事情。

(并且, en passant,让我也说他们实施了“强”与“弱”的引用。但是,这是另一天的另一个故事。)

编辑: 此回复部分不正确!请注意随后在此帖子附带的第一条评论中进行的更正。(并且,“谢谢你让我直截了当!”)关键点(它是一个点...),与前面提到的匿名内存对象包含的内容有关。(它们本身可能包含“引用”。数组经常会这样做!所以,你可以找到“两个独立的内存对象”,引用相同的东西。 Ergo,即使它们确实是“两个完全独立的对象”,但它们在你的程序中实际使用时仍然会相互冲突。(而且,嘿,调试这些东西很有趣。)