【问题标题】:Reassigned hash changes the original hash重新分配的哈希更改了原始哈希
【发布时间】:2019-10-28 14:17:05
【问题描述】:

为什么变量 a 会发生变化,我该如何防止?

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

# >> [:hello]

我看到了使用克隆的响应,并想知道为什么下面的工作以及在哪些情况下需要和不需要 .clone

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

【问题讨论】:

  • 没有哈希值。
  • 哈希和数组是唯一使用指针的地方吗?和所有其他变量不是
  • 它们都是参考。有些对象是可变的(数组、散列、字符串……),但有些不是(数字、符号、……)。
  • @muistooshort:不一定(尽管 OP 不应该阅读此内容,因为它可能会造成混淆)。 CRuby 中的1 不是引用(事实上,-46116860184273879044611686018427387903 之间没有整数)。 nilfalsetrue 也不是引用。我认为浮动可能不是,但不是 100% 肯定。它们都透明地表现得好像它们是,在另一个实现中它们很可能是。
  • @Amadan 但就 Ruby 而言,它们都是参考。对适合指针的数字使用(滥用?)位模式(没有“这是什么东西”位)是一个实现细节。 AFAIK,符号在 C 级别使用类似的技巧。在 Ruby 中,您仍然可以说 6.some_method,所以 6 就像其他任何引用一样。我认为我们在这里分裂头发:)

标签: ruby


【解决方案1】:

据我了解,这是因为内存使用情况。

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

例如,

a = []
a.object_id # 70220203482480
b = a
b.object_id # 70220203482480

当您添加新元素时,这意味着您将值添加到在内存中初始化的数组中,调用ab 都会显示带有新元素的数组。

a.push(1)
b # [1]

让我们看第二个例子

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

c.capitalize! # 'Reference'
d # 'Reference'

如果您分配d = 'new object',Ruby 将在内存中创建另一个对象并将其值作为字符串new object,然后,d 将指向该新内存地址

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

【讨论】:

    【解决方案2】:

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

    a = "string"   #⇒ "string"
    b = a          #⇒ "string"
    b << "changed" #⇒ "stringchanged"
    a              #⇒ "stringchanged"
    

    【讨论】:

      【解决方案3】:

      为什么变量a 会发生变化,我该如何防止?

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

      变量a没有被改变。 唯一的方法可以更改变量是通过分配给它(忽略像Binding#local_variable_set 这样的反射),你没有这样做。因此,a 不会改变。

      ab引用 引用对象 被更改。但是改变object和改变variable是完全不同的两件事。

      我看到了使用克隆的响应,并想知道为什么下面的工作以及在哪些情况下需要和不需要 .clone

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

      这是有效的,因为您永远不会更改对象。你改变变量。

      【讨论】:

        猜你喜欢
        • 2017-05-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-24
        相关资源
        最近更新 更多