当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】:

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

b = a.dup

【讨论】:

【参考方案3】:

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

这种所谓的“浅拷贝”非常有效,而且往往正是我们想要的。所以,这就是这些语言默认做的事情。

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

Ruby ... php ... Perl ... ... 几乎每个人都这样做。

(并且,顺便说一句,我还要说他们实现了“强”与“弱”的引用。但是,这是另一回事了。)

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

【讨论】:

浅拷贝和引用拷贝是不同的东西,a = b表示ab引用同一个对象,浅拷贝(a = b.dup)创建另一个对象,但内部引用不是上当了。深拷贝意味着即使是深度嵌套的对象也会被复制。 优秀的点,mudasobwa。我认为您应该将其作为“答案”以引起更多关注,以便我对其进行投票。 请随意将其放入您的答案中。 我刚做了。 :-) 请查看刚刚修改过的答案,并确定我的“编辑”段落是否正确。再次感谢。

以上是关于当a = b时,Ruby不会创建b的重复变量a吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

Python地址分配给变量

无法理解 ruby​​ 逻辑运算符的结果 [重复]

Ruby 的 max 函数顺序如何重复?

java所有变量定义时都要赋初值吗????

Ruby 奇数逗号与一系列变量一起使用 [关闭]

MySQL可重复读采坑记录-对事务B进行更新时,事务A提交的更新会不会影响到事务B