第二周
七、三大函數
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