類的復制控制
新建一個類對象時,類的構造函數會對其初始化,許多時候需要使用一個已經存在的對象去復制出同類的一個或多個新對象,這個時候就需要使用到類的復制構造函數。有些情況需要同類對象之間互相賦值,就像A=B一樣,這就是賦值函數的工作。當對象的作用域結束或動態分配的對象被刪除時,就應自動調用析構函數釋放對象獲取的所有資源。復制構造函數是一種特殊的構造函數。具有單個形參,這個參數采用對象的引用的形式。賦值函數其實就是賦值操作符=。析構函數是構造函數的互補。
復制構造函數、賦值函數和析構函數總稱為復制控制。當類沒有自己定義這些操作,編譯器會自動提供一套默認的復制控制函數以方便用戶的使用。但編譯器提供的復制控制函數非常精煉,它們只做一些必需的工作——默認復制構造函數只簡單地復制類中每個數據成員的值,默認賦值函數與默認復制構造函數類似執行逐個成員賦值,默認析構函數則什麽都不做。因此,對某些類而言,依賴於默認定義會導致災難性的錯誤,尤其是在類具有指針成員或者類中使用到動態內存分配時,使用默認復制控制函數就只能做到淺拷貝。淺拷貝是指源對象與拷貝對象共用一份實體,僅僅是引用的變量的名稱不同,那麽對於指針,淺拷貝中僅僅是復制了指針變量的值,而並沒有復制指針指向的數據,也即對其中任何一個對象的改動都會影響另外一個對象。這個時候就需要類定義自己的復制控制成員以實現深拷貝。深拷貝是指源對象與拷貝對象互相獨立,改動任何一個對象的都不會對另外一個對象造成影響。
當程序中需要根據另一個同類型的對象顯式或隱式初始化一個對象時,當函數的參數為類對象且采用值傳遞方式時,當函數的返回值是類對象時都需要使用到復制構造函數。撤銷類對象時會自動調用析構函數,所以當函數的返回值是類對象時,在對象值傳遞完畢後就會自動調用析構函數。類對象參與表達式運算時,如A=B+C,在右值計算完畢賦值給左值時需要用到賦值函數。總體來說,如果一個類重載了運算符,那麽在一個運算表達式中將需要使用到所有復制控制函數。根據“三法則”規則,如果類需要析構函數,則它也需要賦值操作符和復制構造函數。
類的復制控制