Ruby 重新分配的哈希将更改原始哈希

Ruby 重新分配的哈希将更改原始哈希,ruby,Ruby,为什么变量a会被更改?我如何防止它 a = [] # => [] b = a # => [] b << :hello # => [:hello] p a # => [:hello] # >> [:hello] a = [] # => [] b = a # => [] b << :hello # => [:hello] p a

为什么变量
a
会被更改?我如何防止它

a = []       # => []
b = a        # => []
b << :hello  # => [:hello]
p a          # => [:hello]

# >> [:hello]
a = []       # => []
b = a        # => []
b << :hello  # => [:hello]
p a          # => [:hello]

据我所知,这是因为内存的使用

初始化对象时,Ruby将首先初始化内存中的对象。然后,变量指向该内存地址。当您将此变量分配给另一个变量时,该变量也将指向该地址

比如说,

a = []
a.object_id # 70220203482480
b = a
b.object_id # 70220203482480
当您添加新元素时,这意味着您将值添加到在内存中初始化的数组中,调用
a
b
都将显示具有新元素的数组

a.push(1)
b # [1]
让我们看看第二个例子

c = 'reference'
d = c
c.object_id #70220203442960
d.object_id #70220203442960

c.capitalize! # 'Reference'
d # 'Reference'
如果分配
d='newobject'
,Ruby将在内存中创建另一个对象,并将其值作为字符串
newobject
,然后,
d
将指向该新内存地址

d = 'new object'
d.object_id # 70220203334840 (different one)
c # 'Reference' (cause c still point to the last object in memory)

为什么对数组使用变异方法,对字符串使用重新绑定,但仍然希望它们的行为类似

a=“字符串”#⇒ “字符串”
b=a#⇒ “字符串”
B
为什么变量
a
会被更改?我如何防止它

a = []       # => []
b = a        # => []
b << :hello  # => [:hello]
p a          # => [:hello]

# >> [:hello]
a = []       # => []
b = a        # => []
b << :hello  # => [:hello]
p a          # => [:hello]
变量
a
未更改。更改变量的唯一方法是分配给它(忽略像
绑定#local_variable_set
这样的反射),而您没有这样做。因此,
a
不会改变

a
b
引用的对象会发生更改。但是改变对象和改变变量是两件完全不同的事情

我看到了对使用克隆的回应,并想知道为什么下面的方法有效,在哪些情况下有效。克隆是需要的,而不是需要的

a = "string"   # => "string"
b =a           # => "string"
b = "changed"  # => "changed"
a              # => "string"
a = "string"   # => "string"
b =a           # => "string"
b = "changed"  # => "changed"
a              # => "string"

这是因为您从不更改对象。您可以更改变量。

没有散列。散列和数组是唯一使用指针的地方吗?所有其他变量都是引用。有些对象是可变的(数组、散列、字符串等),但有些对象不是可变的(数字、符号等)。@muistooshort:不一定(尽管OP不应该读这个,因为它可能会混淆)1
不是引用(实际上,
-4611686018427387904
4611686018427387903
之间没有整数)
nil
false
true
也不是参考。我认为浮动可能也不是,但不是100%确定。它们的行为都是透明的,就像它们是一样,在另一个实现中它们可能是透明的。@Amadan但就Ruby而言,它们都是引用。对适合指针的数字使用(滥用?)位模式(无“what is this thing”位)是一个实现细节。好了,符号在C级使用类似的技巧。在Ruby中,你仍然可以说
6。一些方法
,所以
6
和其他方法一样是一个参考。不过,我认为我们在这方面有些分歧:)