为什么清除哈希表也会清除我的哈希数组?

3
ruby-1.9.2-p180 :154 > a = []
 => []
ruby-1.9.2-p180 :154 > h = {:test => "test"}
 => {:test=>"test"} 
ruby-1.9.2-p180 :155 > a << h
 => [{:test=>"test"}] 
ruby-1.9.2-p180 :156 > h.clear
 => {} 
ruby-1.9.2-p180 :157 > a
 => [{}] 

我非常困惑,特别是因为我可以更改哈希表的元素而不影响数组。但是当我清空哈希表时,数组会被更新并清除其哈希表内容。有人能解释一下吗?


a是什么?你可能在irb中打错了什么,少输入了什么。 - sawa
2个回答

5

当你执行 a << h 时,实际上是将 h 的引用传递给 a。因此,当你更新 h 时,a 也会看到这些变化,因为它包含的是引用而不是该值的副本。

为了使其在 a 中不改变,你必须向 a 传递 h 的克隆值。

例如:

a << h.clone

抱歉,我的问题表述不够清晰。我想知道为什么会发生这种情况,同时也想知道是否有一种方法可以使用clear而不影响数组,或者我必须手动清空哈希表? - Jeremy Smith
如我的答案所示,您可以克隆h(即创建对h中数据的新引用),这样您就可以清除哈希而不影响数组。 - Mike Lewis
1
Ruby 不是 传递引用。它是传递值。始终如此。没有例外。正如在无数次的邮件列表、论坛、博客、StackOverflow、Twitter和其他地方讨论过的那样。 - Jörg W Mittag
@Jorg,更像是“按值传递引用”的语义,微妙而又重要的区别。 - Earlz

1

Ruby 在将哈希添加到数组中时并不会创建一个副本,它只是存储对原始变量的引用。因此,当您清空原始变量时,存储在数组中的引用现在指向空哈希。

如果您想复制哈希元素以避免出现这种情况,请使用 Ruby 的 clone 方法。

ruby-1.9.2-p136 :049 > h = { :test => 'foo' }
 => {:test=>"foo"}
ruby-1.9.2-p136 :050 > a = []
 => [] 
ruby-1.9.2-p136 :051 > a << h.clone
 => [{:test=>"foo"}] 
ruby-1.9.2-p136 :052 > h.clear
 => {} 
ruby-1.9.2-p136 :053 > a
 => [{:test=>"foo"}] 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接