1、如果沒有宣告copy構造方法,copy賦值操作符,和析構方法,編譯器會自動生成這些方法,且是inline。
2、如果沒有宣告任何構造方法,編譯器會自動生成一個default構造方法,且是inline。
3、編譯器總是為我們生成一個合成析構方法。
4、首先考慮,編譯器生成的copy構造方法做什麼事?
copy構造方法是一個特殊的構造方法,形參是const T&。編譯器生成的copy構造方法逐個成員初始化。逐個成員初始化:對於建立物件的每個non-static欄位,使用現有物件的欄位去初始化。
如果欄位是類型別,遞迴呼叫類的copy構造方法。如果是內建型別,逐個bit拷貝。需要注意的是:對於引用和指標,複製引用和指標。不同型別的指標,指明瞭指向物件的型別,但是指標本身是int型別,就是一個地址,引用是用指標實現出來的。因此,對於引用和指標,也是逐個bit拷貝,因為它們本身的型別是int。
還有一個特殊的情況:類中的陣列。一般情況下,陣列是不能賦值的,但是類中的陣列是可以複製的,逐個元素進行拷貝。
對於編譯器生成的copy構造方法,可以這樣認為:在初始化列表中,使用現有物件的每個欄位去初始化正在建立物件的欄位。
5、編譯器生成的copy賦值操作符做什麼事?
copy賦值操作符,就是過載了操作符=,返回T&,形參是const T&。編譯器生成的copy賦值操作符逐個成員賦值。逐個成員賦值:對於當前物件的每個non-static欄位,使用rhs的欄位進行賦值。那麼問題來,
我們知道,類中的有些欄位是隻能初始化,不能賦值的,也就是不能修改。包括:類中的引用和const欄位,這種情況下,編譯器不會為我們生成copy賦值操作符。
還有一種情況,父類的copy賦值操作符是private,編譯器也不會為子類生成copy賦值操作符。為什麼?因為子類期望呼叫父類的copy賦值操作符,對父類的成分賦值,由於父類的copy賦值操作符是private,不能呼叫,編譯器也就不為子類生成copy賦值操作符了。
6、可以認為有兩個析構方法:析構方法和合成析構方法。前者用於釋放動態獲取的資源,後者用於按物件建立的逆序撤銷每個non-static欄位。物件超出作用域,先呼叫析構方法,再呼叫合成析構方法,在合成析構方法中,對於類型別,遞迴呼叫它的析構方法和合成析構方法,對於內建型別,不需要做什麼。
有個三法則:如果類需要析構方法,那麼它也需要自定義copy構造方法和copy賦值操作符。為什麼?怎麼理解?
析構方法,用於釋放動態獲取的資源,定義了析構方法,說明類中有指標。在上文中,我們知道,指標本身是int型別,copy構造和copy賦值的時候,只是拷貝指標值,並沒有拷貝指向的物件,這就導致兩個物件中的指標,指向同一塊資料,這往往不是程式設計師所期望的。因此,需要自定義copy構造和copy賦值,對指向的資料也進行拷貝,也就是深拷貝。
7、編譯器生成的default構造方法,成員初始化列表為空,這就意味著,類中的內建型別欄位沒有被初始化。為了保證物件被使用之前,先被初始化,這情況下需要提供一個構造方法,對內建型別的欄位初始化。