8.7
如果一個類帶有指針揭措,那么類的拷貝構(gòu)造和拷貝賦值一定要自己寫,不能用編譯器的默認版本刻蚯,若使用默認版本進行拷貝绊含,則拷貝后的指針指向被拷貝指針指向的空間,而不再指向自己原來指向的空間炊汹。
字符串類的數(shù)據(jù)成員設(shè)計為字符指針躬充,在需要內(nèi)存的時候才創(chuàng)建一個空間來放字符本身,可以取得動態(tài)分配字符串大小的效果讨便。
拷貝構(gòu)造充甚,構(gòu)造函數(shù)的參數(shù)是同一類型的東西,舉例:
String(const String& str);
拷貝賦值舉例:
String& operator = (const String& str);
在拷貝賦值時霸褒,要先檢測是否為自我賦值伴找,效率高,而且不檢測的話傲霸,后面的代碼清除左邊對象指針?biāo)缚臻g時疆瑰,會把右邊對象指針?biāo)缚臻g也清除了(兩者實際指向同一空間),后續(xù)代碼會產(chǎn)生不確定的行為:
if( this == &str)
return *this;
當(dāng)類對象死亡的時候會調(diào)用析構(gòu)函數(shù)昙啄,將動態(tài)分配的內(nèi)存空間釋放穆役。析構(gòu)函數(shù)舉例:
Inline
String :: ~String()
{
delete [] m_data;
}
9.8
cout可以直接接字符指針,打印出指針?biāo)缸址?/p>
Stack(棧)梳凛,是存在于某作用域(局部)的一塊內(nèi)存空間耿币。例如調(diào)用函數(shù)時,函數(shù)本身即會形成一個stack來放置它所接收的參數(shù)韧拒,以及返回地址和局部對象淹接。在函數(shù)本體內(nèi)聲明的任何變量所使用的內(nèi)存塊都取自棧。棧對象會在作用域結(jié)束之際被析構(gòu)函數(shù)自動清理叛溢。
Heap(堆)塑悼,是指由操作系統(tǒng)提供的一塊全局內(nèi)存空間,程序可動態(tài)分配若干區(qū)塊(new)楷掉。new出來的動態(tài)空間需要手動delete掉厢蒜。array new要搭配array delete,即delete[]烹植,可調(diào)用多次析構(gòu)函數(shù)斑鸦。
靜態(tài)對象的生命在作用域結(jié)束之后仍然存在,直到整個程序結(jié)束草雕,舉例:
{
static?Complex c2(1,2);
}
在全局作用域中聲明的對象也是全局對象巷屿,其生命在整個程序結(jié)束之后才結(jié)束。
{
Complex* p = new Complex墩虹;
...
delete p;
}
P所指的便是heap object嘱巾,其生命在它被delete之際結(jié)束憨琳。
{
Complex* p = new Complex;
}
以上會出現(xiàn)內(nèi)存泄露(memory leak)浓冒,因為當(dāng)作用域結(jié)束栽渴,p所指的heap object仍然存在,但指針p的生命卻結(jié)束了稳懒,作用域之外再也看不到p(也就沒機會delete p)
VC下分配的動態(tài)內(nèi)存塊大小一定是16的倍數(shù)(字節(jié)數(shù))闲擦。
在類成員前面加關(guān)鍵字static,則成為靜態(tài)成員场梆。靜態(tài)數(shù)據(jù)成員只有一份墅冷,為同一類的所有對象共有。靜態(tài)成員函數(shù)沒有this指針或油,只能存取靜態(tài)數(shù)據(jù)寞忿。
靜態(tài)數(shù)據(jù)要在類之外定義,舉例:
class Account
{
public:
static double m_rate; //聲明
static void set_rate (const double& x) {m_rate=x}顶岸;
}
double Account::m_rate=8.0 //定義
調(diào)用靜態(tài)函數(shù)的方式:
[if !supportLists](1)[endif]通過對象調(diào)用腔彰;
[if !supportLists](2)[endif]通過類名調(diào)用,如:Account::set_rate(5.0)
使用命名空間可以避免自己寫的東西和別人寫的東西重名引起的沖突辖佣。
namespace std //名字自己取
{
...
}