【问题标题】:How to understand the #dup and #clone operate on objects which referencing other objects?如何理解#dup 和#clone 对引用其他对象的对象进行操作?
【发布时间】:2013-04-18 01:24:19
【问题描述】:

我不确定rubyrubinus 的文档中“...但不是他们引用的对象” 的含义。

ruby-doc中,有#clone#dup行为的解释说:

产生 obj 的浅拷贝——obj 的实例变量是 复制,但不是它们引用的对象。复制冻结和 obj 的污染状态。另请参阅 Object#dup 下的讨论。

Rubinius的实现也是如此重复:

复制实例变量,但不递归复制对象 他们参考。复制污点。

我尝试了以下代码,但行为出乎我的意料。

class Klass
   attr_accessor :array
end

s1 = Klass.new
ar = [1, 2, 3]
s1.array = [ar]

s2 = s1.clone
# according to the doc,
# s2.array should be initialized with empty Array
# however the array is recursivley copied too

s2.array.equal? s1.array # true

【问题讨论】:

    标签: ruby object clone dup


    【解决方案1】:

    “相等?”比较检查它们是否是完全相同的对象:

    • == 比较检查两个值是否相等
    • 当量?检查两个值是否相等且类型相同
    • 相等?检查两个事物是否是同一个对象。

    例如:

    a=[1,2]
    => [1, 2] 
    a == [1,2]
    => true 
    a.eql? [1,2]
    => true 
    a.equal? [1,2]
    => false 
    a.equal? a
    => true
    

    当您使用 equal 进行测试时?它显示副本没有创建未初始化数组的对象,但它已使复制的对象指向与原始对象相同的数组。如果它递归地复制对象 s2.array 将具有与 s1.array 相同的内容,但将是一个不同的对象,所以:

    s2.array.equal? s1.array # false
    s2.array.eql? s1.array # true
    

    【讨论】:

    • 这如何回答这个问题?
    【解决方案2】:

    在 Ruby 中,所有对象都是引用。看看下面的例子:

    class Klass
      attr_accessor :a
    end
    
    s1 = Klass.new
    a = [1,2,3]
    s1.a = a
    s2 = s1.clone
    s1.a.object_id  #=> 7344240 
    s2.a.object_id  #=> 7344240 
    

    您可以看到两个数组都是同一个对象,并且都是对位于堆中某处的数组的引用。在深拷贝中,数组本身将被复制,而新的s2 将拥有自己的不同数组。数组没有复制,只是引用。

    注意: 如果你做一个深拷贝,下面是它的样子:

    s3 = Marshal.load(Marshal.dump(s1)) #=> #<Klass:0x00000000bf1350 @a=[1, 2, 3, 4], @bork=4> 
    s3.a << 5 #=> [1, 2, 3, 4, 5] 
    s1 #=> #<Klass:0x00000000e21418 @a=[1, 2, 3, 4], @bork=4> 
    

    【讨论】:

    • 我认为第二个s1.a.object_id #=&gt; 7344240 应该是s2.a.object_id。尽管它们确实引用了相同的数组对象。
    • 所以“...不会递归复制它们引用的对象。”意思是,只复制引用者(指针),而不是引用,对吧?
    • @steven.yang:哎呀!谢谢。
    • 所以,我在问题中写的行为正是应该实现的。明白了。
    猜你喜欢
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-15
    相关资源
    最近更新 更多