第二周
七、三大函數(shù)
1.三大函數(shù)
Class without pointer member-complex
Class with pointer member-string
拷貝構(gòu)造 String s3(s1)
拷貝賦值 s3=s2
如果沒有寫拷貝構(gòu)造和拷貝賦值,編譯器會給一套,一個位一個位復(fù)制。如果編譯器給的夠用,不用寫,比如前面的complex。帶指針的類不能用編譯器給的默認版本,要自己寫。
除了構(gòu)造函數(shù),還有三大函數(shù):
(1)拷貝構(gòu)造
(2)拷貝賦值
(3)析構(gòu)函數(shù)(清理動態(tài)分配的內(nèi)存)
2.析構(gòu)函數(shù)
{
String s1()
String s2(“hello”)
String * p = new String(“hello”)
delete p
}
離開作用域自動析構(gòu),p為什么手動析構(gòu)。
3.Class with pointer members必須有copy ctor和copy op=
使用默認拷貝構(gòu)造或拷貝賦值(淺拷貝)
(1)內(nèi)存泄漏
(2)兩個對象指向同一塊內(nèi)存(alias)
4.拷貝構(gòu)造函數(shù)
深拷貝,要分配足夠的空間,把內(nèi)容拷貝進去。編譯器給的默認版本只拷貝指針,淺拷貝。

5.拷貝賦值函數(shù)
先把左邊內(nèi)容清空,分配一個和右邊一樣大的空間,把右邊的內(nèi)容復(fù)制進去。

八、堆、棧與內(nèi)存管理
1.stack和heap
Stack 是存在于某作用域的一塊內(nèi)存空間。當調(diào)用函數(shù),函數(shù)本身即會形成一塊stack來放置它所接收的參數(shù),以及返回地址。在函數(shù)本體內(nèi)聲明的任何變量,其所使用的內(nèi)存塊都取自上述stack。
Heap 是指由操作系統(tǒng)提供的一塊global內(nèi)存空間,程序可動態(tài)分配從中獲得若干區(qū)塊。
{
??? Complex c1(1,2);
}
Stack object,其生命在作用域結(jié)束之際結(jié)束。這種作用域內(nèi)的object,稱為auto object,因為它會被自動清理,自動調(diào)用析構(gòu)函數(shù)。
{
??? Static Complex c2(1,2);
}
Static object,其生命在作用域結(jié)束之后仍然存在,直到整個程序結(jié)束。
Complex c1(1,2);
int main()
{
}
Global object,其生命在真?zhèn)€程序結(jié)束之后才結(jié)束。也可以把它視為一種static object,其作用域是整個程序。
Heap object,其生命在它被delete之際結(jié)束。如果沒有delete,會出現(xiàn)內(nèi)存泄漏。因為當作用域結(jié)束,p所指的heap object仍然存在,但指針p的生命卻結(jié)束了,作用域之外再也卡不到p,也就沒有機會delete p。
補充:C++內(nèi)存管理
本期專題將從內(nèi)存管理、內(nèi)存泄漏、內(nèi)存回收這三個方面來探討C++內(nèi)存管理問題。
http://blog.csdn.net/zhanghefu/article/details/5003407
在C++中,內(nèi)存分成5個區(qū),他們分別是堆、棧、自由存儲區(qū)、全局/靜態(tài)存儲區(qū)和常量存儲區(qū)。
棧,在執(zhí)行函數(shù)時,函數(shù)內(nèi)局部變量的存儲單元都可以在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時這些存儲單元自動被釋放。棧內(nèi)存分配運算內(nèi)置于處理器的指令集中,效率很高,但是分配的內(nèi)存容量有限。
堆,就是那些由new分配的內(nèi)存塊,他們的釋放編譯器不去管,由我們的應(yīng)用程序去控制,一般一個new就要對應(yīng)一個delete。如果程序員沒有釋放掉,那么在程序結(jié)束后,操作系統(tǒng)會自動回收。
自由存儲區(qū),就是那些由malloc等分配的內(nèi)存塊,他和堆是十分相似的,不過它是用free來結(jié)束自己的生命的。
全局/靜態(tài)存儲區(qū),全局變量和靜態(tài)變量被分配到同一塊內(nèi)存中,在以前的C語言中,全局變量又分為初始化的和未初始化的,在C++里面沒有這個區(qū)分了,他們共同占用同一塊內(nèi)存區(qū)。
常量存儲區(qū),這是一塊比較特殊的存儲區(qū),他們里面存放的是常量,不允許修改。
2.new
new,先分配memory,再調(diào)用ctor。

第3步怎么調(diào)用構(gòu)造函數(shù)?
3.delete
delete:先調(diào)用dtor,再釋放memory

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

調(diào)試模式,vc分配的內(nèi)存塊是16的倍數(shù),52->64
Release mode,16
上下cookie記錄整塊給的大小,41(應(yīng)該是40,最后一個bit表示給出去還是收回來
5.動態(tài)分配所得的數(shù)組

vc用一個整數(shù)記錄3
array new 一定要搭配array delete

九、復(fù)習String類的實現(xiàn)
1.構(gòu)造函數(shù)、拷貝構(gòu)造和拷貝賦值不能用const成員函數(shù),因為都要賦值,改變了成員數(shù)據(jù)。
2.拷貝賦值返回值,因為從c習慣延續(xù)的連續(xù)賦值,所以返回值不能是void,必須是String&。
3.拷貝賦值要判斷是不是自我賦值,if(this=&str) return *this。
4.引用(&出現(xiàn)在type name后面)和取地址(&出現(xiàn)在object前面)
十、擴展補充:類模板、函數(shù)模板和其他
1.static
this pointer
成員函數(shù)只有一份,成員函數(shù)都有一個隱藏的參數(shù)this pointer,通過this pointer找到它要處理的對象。
static data members
static member functions
靜態(tài)成員函數(shù)沒有this pointer,只能處理靜態(tài)數(shù)據(jù)。

注意靜態(tài)成員數(shù)據(jù)的定義(初始化)。
2.把構(gòu)造函數(shù)放在private區(qū)


3.cout
為什么cout能夠接受各種類型的對象,操作符<<重載?
4.class template,類模板

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

類模板要明確指出type要綁定為什么,函數(shù)模板不用明確指出,因為編譯器會做實參推導(dǎo)。
C++標準庫中的算法都是函數(shù)模板。
6.namespace
標準庫中所有都包含在std中。
使用標準庫中的東西:
using directive
using namespace std;
全部打開
using declaration
using std::cout;
一條一條打開
直接std::cout