【问题标题】:Implementing deep clone()实现深度克隆()
【发布时间】:2017-09-01 15:40:48
【问题描述】:
考虑一些 OOP 语言(它是哪一种并不重要)并假设语言创建者想要为每个类添加一个 deep clone() 方法。此外,假定堆被实现为树。
语言创建者应该如何实现它?
所以基本上我们可以(在编译时自动)实现一个 clone() 方法并将其添加到适当的函数虚拟表中。
它将 malloc() 在运行时已知的正确大小并从源复制到目标。最后,它会返回指向 malloced 内存的指针。
如果一个字段是指向某个对象的指针,我们将激活它的 clone() 并将结果作为该字段的值。
如果堆不是“基于树的”会出现什么问题?
所以我真的不知道答案是什么。我的意思是,为什么堆是如何实现的?我很乐意在这里提供帮助。
谢谢。
【问题讨论】:
标签:
oop
memory
compiler-construction
heap-memory
【解决方案1】:
只要对象结构是非循环的,即形成一棵树,您描述的算法就可以正常工作。然后,确实可以对对象进行浅层克隆,然后使用相同的技术继续更新引用其他对象的字段。
但是,如果存在循环(即对象结构没有形成树),算法将永远运行。在最简单的情况下,初始对象o 引用自身:o -> o。当创建一个浅克隆c1 时,新对象仍然引用旧对象:c1 -> o。此外,旧对象没有改变,即我们有c1 -> o -> o。根据该算法,应创建从克隆引用的对象的克隆。因为这是一个新对象,所以它不同于c1。所以,图片变成了c1 -> c2 -> o。这已经是错误的,因为深度克隆应该创建的是c1 -> c1。坏消息是c2 现在也成为处理对象。所以,我们得到c1 -> c2 -> c3 -> o,等等。算法永远循环(直到没有更多的内存来创建新对象)。
为了使算法正常工作,它应该跟踪哪些旧对象已被处理以及为它们创建了哪些新对象。然后,与其盲目地对引用的对象进行新的克隆,不如检查一个旧对象是否已经被克隆,如果是,则使用这个克隆而不是创建一个新的。