当a = b时,Ruby不会创建b的重复变量a吗? [复制]
Posted
技术标签:
【中文标题】当a = b时,Ruby不会创建b的重复变量a吗? [复制]【英文标题】:Does Ruby not create a duplicate variable a of b, when a = b? [duplicate] 【发布时间】:2016-10-27 04:34:36 【问题描述】:在编写程序时,我发现了一些有趣的东西。如果我定义a = b
,我将<<
到b
的任何更改都反映在a
中,反之亦然。
Ruby 不会创建 b 的重复自主副本并将其以不同的方式存储在 a 中吗?
如果没有,我如何在对主阵列进行操作的同时,存储阵列在特定时间点的未篡改快照?
>> 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?!
【问题讨论】:
作为旁注,请阅读:***.com/questions/1872110/… 【参考方案1】:使用Object#dup
。
NB 它确实创建了一个浅拷贝;要创建深层副本,需要自己实现副本。
▶ b = [0, 1]
#⇒ [ 0, 1 ]
▶ a = b.dup
#⇒ [ 0, 1 ]
▶ b << 2
#⇒ [ 0, 1, 2 ]
▶ a
#⇒ [ 0, 1 ]
要制作冻结和污染的副本,请使用Object#clone
。
【讨论】:
【参考方案2】:a
和 b
指向内存中的同一个对象。如果您想要一个对象的副本而不影响原始对象,您可以这样做
b = a.dup
【讨论】:
【参考方案3】:让我试着澄清一下这里到底发生了什么。这是许多语言实现的引用的基本概念。例如,当您创建“一个数组”时,该数组值是一个匿名内存对象,并且在您的代码中,a
和 b
都指的是 same 对象。该语言使用“引用计数”的一些变体来跟踪存在多少引用,以便知道值何时被“孤立”并且可以被垃圾收集。
这种所谓的“浅拷贝”非常有效,而且往往正是我们想要的。所以,这就是这些语言默认做的事情。
当您创建“深层副本”时,您有意识地复制匿名内存对象。现在,a
指向一个,b
指向另一个对象,该对象(在那个时刻)是第一个对象的快照。相比之下,这是一个耗时的过程,当然,它会分配更多的内存。现在,对一个数组所做的更改(当然)不会反映在另一个数组中,因为它们现在是两个完全不同的东西。由于这是一种不太常见的事情,因此该语言提供了一些明确的方式让您指定您想要这样做。
Ruby ... php ... Perl ... ... 几乎每个人都这样做。
(并且,顺便说一句,我还要说他们实现了“强”与“弱”的引用。但是,这是另一回事了。)
编辑: 此回复部分不正确!请注意随后在此帖子所附的第一条评论中进行的更正。(并且,“谢谢你让我直截了当!”)关键点(它是一个 key 点...),与上述匿名内存对象可能包含的内容有关.(它们本身可能包含“引用”。数组经常这样做!因此,您可能会得到“两个独立的内存对象”,它们引用相同的东西。因此, 尽管它们确实是“两个完全独立的对象”,但在你的程序中实际使用时,它们仍然可能相互冲突。(呵呵,调试这样的东西很有趣。)
【讨论】:
浅拷贝和引用拷贝是不同的东西,a = b
表示a
和b
引用同一个对象,浅拷贝(a = b.dup
)创建另一个对象,但内部引用不是上当了。深拷贝意味着即使是深度嵌套的对象也会被复制。
优秀的点,mudasobwa。我认为您应该将其作为“答案”以引起更多关注,以便我对其进行投票。
请随意将其放入您的答案中。
我刚做了。 :-) 请查看刚刚修改过的答案,并确定我的“编辑”段落是否正确。再次感谢。以上是关于当a = b时,Ruby不会创建b的重复变量a吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章