Boolan C++面向對象高級編程(上)第二周

第二周

七、三大函數

1.三大函數

Class without pointer member-complex

Class with pointer member-string

拷貝構造 String s3(s1)

拷貝賦值 s3=s2

如果沒有寫拷貝構造和拷貝賦值,編譯器會給一套,一個位一個位復制。如果編譯器給的夠用,不用寫,比如前面的complex。帶指針的類不能用編譯器給的默認版本,要自己寫。

除了構造函數,還有三大函數:

(1)拷貝構造

(2)拷貝賦值

(3)析構函數(清理動態(tài)分配的內存)

2.析構函數

{

String s1()

String s2(“hello”)

String * p = new String(“hello”)

delete p

}

離開作用域自動析構,p為什么手動析構。

3.Class with pointer members必須有copy ctor和copy op=

使用默認拷貝構造或拷貝賦值(淺拷貝)

(1)內存泄漏

(2)兩個對象指向同一塊內存(alias)

4.拷貝構造函數

深拷貝,要分配足夠的空間,把內容拷貝進去。編譯器給的默認版本只拷貝指針,淺拷貝。

5.拷貝賦值函數

先把左邊內容清空,分配一個和右邊一樣大的空間,把右邊的內容復制進去。

八、堆、棧與內存管理

1.stack和heap

Stack 是存在于某作用域的一塊內存空間。當調用函數,函數本身即會形成一塊stack來放置它所接收的參數,以及返回地址。在函數本體內聲明的任何變量,其所使用的內存塊都取自上述stack。

Heap 是指由操作系統(tǒng)提供的一塊global內存空間,程序可動態(tài)分配從中獲得若干區(qū)塊。

{

??? Complex c1(1,2);

}

Stack object,其生命在作用域結束之際結束。這種作用域內的object,稱為auto object,因為它會被自動清理,自動調用析構函數。

{

??? Static Complex c2(1,2);

}

Static object,其生命在作用域結束之后仍然存在,直到整個程序結束。

Complex c1(1,2);

int main()

{

}

Global object,其生命在真?zhèn)€程序結束之后才結束。也可以把它視為一種static object,其作用域是整個程序。

Heap object,其生命在它被delete之際結束。如果沒有delete,會出現(xiàn)內存泄漏。因為當作用域結束,p所指的heap object仍然存在,但指針p的生命卻結束了,作用域之外再也卡不到p,也就沒有機會delete p。

補充:C++內存管理

本期專題將從內存管理、內存泄漏、內存回收這三個方面來探討C++內存管理問題。

http://blog.csdn.net/zhanghefu/article/details/5003407

在C++中,內存分成5個區(qū),他們分別是堆、棧、自由存儲區(qū)、全局/靜態(tài)存儲區(qū)和常量存儲區(qū)。

棧,在執(zhí)行函數時,函數內局部變量的存儲單元都可以在棧上創(chuàng)建,函數執(zhí)行結束時這些存儲單元自動被釋放。棧內存分配運算內置于處理器的指令集中,效率很高,但是分配的內存容量有限。

堆,就是那些由new分配的內存塊,他們的釋放編譯器不去管,由我們的應用程序去控制,一般一個new就要對應一個delete。如果程序員沒有釋放掉,那么在程序結束后,操作系統(tǒng)會自動回收。

自由存儲區(qū),就是那些由malloc等分配的內存塊,他和堆是十分相似的,不過它是用free來結束自己的生命的。

全局/靜態(tài)存儲區(qū),全局變量和靜態(tài)變量被分配到同一塊內存中,在以前的C語言中,全局變量又分為初始化的和未初始化的,在C++里面沒有這個區(qū)分了,他們共同占用同一塊內存區(qū)。

常量存儲區(qū),這是一塊比較特殊的存儲區(qū),他們里面存放的是常量,不允許修改。

2.new

new,先分配memory,再調用ctor。

第3步怎么調用構造函數?

3.delete

delete:先調用dtor,再釋放memory

4.動態(tài)分配所得的內存塊,in VC

調試模式,vc分配的內存塊是16的倍數,52->64

Release mode,16

上下cookie記錄整塊給的大小,41(應該是40,最后一個bit表示給出去還是收回來

5.動態(tài)分配所得的數組

vc用一個整數記錄3

array new 一定要搭配array delete

九、復習String類的實現(xiàn)

1.構造函數、拷貝構造和拷貝賦值不能用const成員函數,因為都要賦值,改變了成員數據。

2.拷貝賦值返回值,因為從c習慣延續(xù)的連續(xù)賦值,所以返回值不能是void,必須是String&。

3.拷貝賦值要判斷是不是自我賦值,if(this=&str) return *this。

4.引用(&出現(xiàn)在type name后面)和取地址(&出現(xiàn)在object前面)

十、擴展補充:類模板、函數模板和其他

1.static

this pointer

成員函數只有一份,成員函數都有一個隱藏的參數this pointer,通過this pointer找到它要處理的對象。

static data members

static member functions

靜態(tài)成員函數沒有this pointer,只能處理靜態(tài)數據。

注意靜態(tài)成員數據的定義(初始化)。

2.把構造函數放在private區(qū)

3.cout

為什么cout能夠接受各種類型的對象,操作符<<重載?

4.class template,類模板

編譯器會把T全部替換為double,得到一份代碼;把T全部替換為int,得到一份代碼。使用模板會使代碼膨脹(不是缺點)。

5.function template,函數模板

類模板要明確指出type要綁定為什么,函數模板不用明確指出,因為編譯器會做實參推導。

C++標準庫中的算法都是函數模板。

6.namespace

標準庫中所有都包含在std中。

使用標準庫中的東西:

using directive

using namespace std;

全部打開

using declaration

using std::cout;

一條一條打開

直接std::cout

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容