复制构造函数应该有多深


  1. 是否应该始终为传递给构造函数的可变对象的对象引用创建防御副本?

  2. 如果是的话,那么我应该在复印方面深入到什么程度。在下面的例子中,我应该在所有涉及的类的复制构造函数中进行深度复制吗?

例如:

class Graph {
    AdjacencyList;
    public Graph(Graph graph) {
      this.list = graph.list;   // shallow copy
      OR
      this.list = ArrayCopy(graph.list);  // deep copy
    }
}
class DFS implements GraphAlgo {
   Graph g
   DFS(Graph g) {
     this.g = g;   // shallow copy
     OR
     this.g = new Graph(graph)  // deep copy
   }
   DFS(Algo algo) {
     this.g = algo.g;  // shallow copy
     OR
     this.g = new Graph(algo.g);  // deep copy
   }
}
class Algo {
   GraphAlgo galgo
   Algo (GraphAlgo dfsalgo) {
      galgo  = dfsalgo  // shallow copy
      OR
      galgo = new DFSAlgo(dfsalgo); // deep copy
   }
}

3.如果某个类忘记实现深度复制怎么办?这是否意味着我永远不会有一个安全的深度复制对象?有什么办法可以防止这种情况发生吗?

你应该采取防御措施吗
只有当你需要的时候。

你应该走多远
尽可能深入。

听起来很老套?好吧,这类问题的基本答案是"尽可能少地提供所需的功能"。

一般情况下:除非您不信任调用代码,否则不要进行防御性复制。

Do:记录接口,并表示如果会导致问题,他们不允许更改传递给您的任何内容。

有时:提供两个构造函数。一个使用对象。一个人复印一份。然后让呼叫者在需要时呼叫制作副本的呼叫者。调用者很可能在调用构造函数之后就放弃对该对象的任何引用。在这种情况下,不需要任何副本。

Algo (GraphAlgo dfsalgo, boolean doCopy) {
    if (doCopy) {
        galgo = new DFSAlgo(dfsalgo); // deep copy
    } else {
        galgo  = dfsalgo  // shallow copy
    }
}

如果您信任调用代码:忽略此问题。在调用您的代码之前,期望它复制任何不会丢弃的东西(从它自己的角度来看)。

偏执狂并不意味着他们不想抓住你。但这并不意味着他们也是

最新更新