1.BIG THREE 三個特殊函數
1.1析構函數
在設計類的時候分配了資源,而這些資源,成員函數又不會自動釋放,那么就需要一個析構函數,析構函數在創建的對象消亡的時候會自動被編譯器調用。特別是那些構造函數中使用了new表達式的類,通常要在析構函數中加上對應的delete,否則會造成內存泄漏。
1.2拷貝構造
帶有指針的類必須要自己寫拷貝構造函數和拷貝賦值函數,因為如果使用編譯器給的默認拷貝構造函數,只是將a的地址拷貝到b中去,并沒有拷貝a的m_data指向的那個內容,使得a的m_data和b的m_data指向同一個地方,b的m_data原本指向的“World”就成了一個孤立的內容,這樣會造成內存泄漏。而且因為a和b都指向一塊內存,更改a就會影響b,也是一個隱患,這個被稱為淺拷貝,默認的拷貝屬于淺拷貝,只是單純地一個位一個為把值復制給想賦值的對象。所以要使用深拷貝的方法,即自己寫一個拷貝構造函數。
1.3拷貝賦值
切記自我賦值檢測,如果沒有自我賦值檢測,delete[] m_data這一步驟會把自己的內容刪掉,產生不確定行為。
2.堆、棧與內存管理
2.1棧(heap)
棧為函數內部聲明的局部變量提供了存儲空間,他的生命在作用域結束之際結束,這些變量就是auto變量。進行函數調用的時候,棧存儲與此有關的維護信息,這些性息就是過程活動記錄,他包含函數調用的地址(就是調用函數結束后返回的地方),還有一些不適合放到寄存器中的變量的值和寄存器值的保存,調用函數時起到保存現場的作用。棧也被作為臨時區使用,比如表達式很長,其中還有幾個函數調用,這個時候就會利用棧,把先計算出來的值臨時存放,要使用時在拿出來計算。
2.2堆(stack)
堆是指由操作系統提供的一塊全局內存空間,程序可以手動分配和釋放。
需要注意的是內存泄漏,在作用域結束之前,指針指向的堆的內存依舊存在,如若走出作用域之前未delete,在作用域之外沒有機會使用delete,就會造成內存泄漏,切記new和delete一定是成對出現的。
new的步驟:(1)進行內存分配(使用malloc)(2)轉型(3)調用構造函數
new在創建對象的時候會去調用構造函數之間初始化對象,但是malloc必需手動的賦值。
delete的步驟:(1)調用析構函數(2)free
delete在對象被銷毀之前,會去調用類內對應的析構函數,這就意味著,可以在對象銷毀時做更多的事情,free只是單純的釋放內存。
3.內存管理
3.1cookies用來記所分配內存塊的大小,大小是16bit的倍數,末位表示輸入(0)和輸出(1);灰色部分表示debug代碼區,不需要調試可以不要;淺綠色表示對象所存在的內存區域;深綠色是為了使分配的內存為16的倍數所填補的,稱為pad。
3.2array new一定要搭配array delete,否則也會造成內存泄漏。
4.static
4.1非靜態成員變量中,使用者如圖創建了三個對象,在內存模型中,每個對象都有一份成員變量,通過this指針(每個對象的地址)來區別是哪個對象調用對應的成員變量。同樣的一份成員函數處理多個對象的需求也是通過this指針實現的。
4.2在成員變量或者成員函數前面加上關鍵字static,那么就變成靜態的成員變量和靜態的成員函數,脫離了對象,只有一份。應用比如設計一種銀行賬戶體系,用戶的賬號是每一個對象,銀行的利率和對象無關,這時把利率設計成靜態的成員變量。靜態成員函數沒有this pointer,不能像一般的成員函數一樣去訪問、處理對象里面的數據,靜態函數只能處理靜態的數據。靜態的數據在class的外頭必須要定義,初值可以給也可以不給。
調用static函數的方式有兩種:(1)通過object調用;(2)通過class name調用。
就寫這么多,回頭要多看看。