【问题标题】:Weird behaviour copying objects复制对象的奇怪行为
【发布时间】:2015-01-09 21:16:20
【问题描述】:

我正在尝试深度复制一个包含 3D 数组的对象。但它没有按预期工作。

class A
    def initialize
        @a = [[[1]], [[2]]]
    end

    def modify3D
        @a[0][0] = @a[1][0]
    end

    def modify2D
        @a[0] = @a[1]
    end

    def dup
        copy = super
        copy.make_independent!
        copy
    end

    def make_independent!
        @a = @a.dup
    end

    def show
        print "\n#{@a}"
    end
end

a = A.new
b = a.dup
#a.modify2D
b.show
a.modify3D
b.show

在这种情况下,b 被 a 上的 modify3D 调用更改。

[[[1]], [[2]]]
[[[2]], [[2]]]

如果我取消注释 modify2D 行一切正常。

[[[1]], [[2]]]
[[[1]], [[2]]]

有人能解释一下这里发生了什么吗?

【问题讨论】:

    标签: ruby deep-copy


    【解决方案1】:

    您的副本不够深。 Array#dup 只复制数组本身,而不是数组元素。您最终会得到两个仍然共享相同元素的不同数组。

    this answer 中,我展示了如何使用marshaling 进行深层复制。此方法完成所有工作:

    def deep_copy(o)
      Marshal.load(Marshal.dump(o))
    end
    

    deep_copy 适用于任何可以编组的对象。大多数内置数据类型(数组、哈希、字符串等)都可以编组。可以对实例变量进行封送处理的任何对象本身都可以进行封送处理。

    定义了 deep_copy,然后替换这一行:

    b = a.dup
    

    用这个:

    b = deep_copy(a)
    

    它应该可以按您的预期工作。

    【讨论】:

    • 您的解决方案运行良好,但我仍然无法解释为什么取消注释该行使其工作。根据你的解释,应该不会。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-13
    相关资源
    最近更新 更多