當處理複雜的資料結構和對象時,程式設計中的很多最基本的操作會變得越來越複雜。例如,當你想複制或比較原始資料類型時,過程非常簡單。然而,複制和比較對象則并不簡單。《effective c++》第34頁中,scott meyers專門花了整個小節來講述複制和配置設定對象。
類和引用
複雜的資料結構和對象的問題在于它們可能會包含引用。簡單對引用的複制不能複制它引用的資料結構或對象。同樣,當比較對象時,簡單地比較兩個指針隻是比較了引用,而并未比較指針所指的對象。
當對對象進行比較和複制時你就會意識到該問題。具體來說,問題歸結于你是否使用了指針。不管怎樣,總有一種方式能複制對象。不過這種方式看上去簡單,但實際并不簡單。因為對象可以包含引用,而必須對整個引用樹做有效的複制(如果你要建立一份深拷貝)。
深拷貝與淺拷貝
追蹤所有的引用,并對所有引用對象都建立拷貝,這種方式稱為深拷貝。深拷貝會擁有很多層級。一個對象引用了很多對象,而這些被引用的對象也可能引用其他對象。拷貝本身開銷巨大。淺拷貝隻會簡單地拷貝引用,而不會深入層級。在《java面向對象設計》一書第265頁的“隻見樹木不見森林”一節中,gilbert和mccarty對深拷貝和淺拷貝進行了精彩的讨論。
如圖3-8所示,如果隻是簡單地拷貝對象(稱為逐位複制),隻會拷貝引用,而不會拷貝實際的對象。是以,兩個對象(原始對象和副本)會引用(指向)同一個對象。為了完全複制(即需要複制每個引用對象),你必須編寫代碼來建立所有的子對象。

當比較對象時也有類似的問題。正如拷貝功能一樣,比較功能并不像看起來那麼簡單。因為對象包含引用,必須根據引用樹進行有效的對象比較。大多數情況下,語言提供了一種預設的機制來比較對象。當設計類時,你應當在類中提供一個比較功能,進而保證類的行為是預期的。