課堂筆記:
三個(gè)特殊函數(shù):
String(const String& str);//拷貝構(gòu)造函數(shù)
String& operator=(const String& str);//拷貝賦值函數(shù)
~String()檩赢;//析構(gòu)函數(shù)
在內(nèi)外調(diào)用析構(gòu)函數(shù)時(shí)痴腌,需要寫全名黍翎;
析構(gòu)函數(shù)起到關(guān)門清理函數(shù)的作用;
如果沒(méi)有把內(nèi)存釋放掉的話蜡秽,內(nèi)存就會(huì)溢出
如果class里有指針,多半是要進(jìn)行動(dòng)態(tài)分配
動(dòng)態(tài)創(chuàng)建對(duì)象的方式:
string *p = new String("Hello");
delete p;
String s2(s1);//以s1為藍(lán)本創(chuàng)建對(duì)象s2
m_data = new char [ strlen(str.m_data)+1];
strcpy(m_data,str.m_data);//深拷貝
創(chuàng)造足夠的空間給藍(lán)本
拷貝賦值函數(shù):
if(this == &str)
return *this;//檢測(cè)自我賦值
output函數(shù):
不能寫成成員函數(shù),寫成全局函數(shù)掩宜,有兩個(gè)參數(shù)
ostream& operator<<( ostream& os, const String& str );
stack(棧):是存在于某種作用域的一塊內(nèi)存空間。當(dāng)調(diào)用函數(shù)么翰,函數(shù)本身會(huì)形成一個(gè)stack用來(lái)放置它所接收的參數(shù)以及返回地址牺汤。在函數(shù)本體內(nèi)聲明的任何變量,其所使用的內(nèi)存塊都取自上述stack浩嫌。只要離開(kāi)作用域檐迟,其生命周期結(jié)束,自動(dòng)調(diào)用析構(gòu)函數(shù)码耐。
{
Complex c1(1,2)追迟;
}
heap(堆):由操作系統(tǒng)提供的一塊全局內(nèi)存空間,程序可動(dòng)態(tài)分配從中獲得若干塊骚腥。
{
Complex *p = new Complex(3);
}
要手動(dòng)delete
可以在任何地方以new的方式敦间,動(dòng)態(tài)的獲得
static object,其生命在作用域結(jié)束之后仍然存在,直到程序結(jié)束
static_cast 類型轉(zhuǎn)換
array new 一定要搭配 array delete
static:
只能處理靜態(tài)的數(shù)據(jù)
調(diào)用方式:1.通過(guò)object調(diào)用廓块;2.通過(guò)class name調(diào)用
對(duì)operator = 中處理“自我賦值”進(jìn)行深入學(xué)習(xí):
例如下列代碼:
class Comolex { . . . };
Conplex x;
. . .
x = x;//自己賦值給自己
這樣看起來(lái)可能有點(diǎn)笨厢绝,但是編譯是能通過(guò)的,此外賦值動(dòng)作不是總是一眼就能被辨識(shí)出來(lái):
a[i] = a[j] ; ? ? //自我賦值
如果i和j有相同的值带猴,這就是個(gè)自我賦值昔汉。
*px = *py; ? ?//這也是自我賦值
如果px和py恰巧指向同一個(gè)東西拴清,這也是自我賦值靶病。這些自我賦值并不明顯,但都是因?yàn)椤皠e名”帶來(lái)的結(jié)果口予。一班來(lái)說(shuō)嫡秕,如果某段代碼操作pointers 或者 references 而它們被用來(lái)指向多個(gè)相同的類型的對(duì)象,就需要考慮這些對(duì)象是否是同一個(gè)苹威。只要兩個(gè)對(duì)象來(lái)自同一個(gè)繼承體系昆咽,它們不需要進(jìn)行聲明成相同的類型就能造成“別名”的現(xiàn)象,這是因?yàn)檠栏Γ粋€(gè)基類的引用或指針可以指向一個(gè)派生類對(duì)象:
class Base ?{ . . . ?} 掷酗;
clase Derived : public Base { . . .? } ;
void complex (const Base& x, Derived* y); ? ? //x和y有肯能其實(shí)是同一對(duì)象
下面是operator=實(shí)現(xiàn)代碼窟哺,雖然表面上看起來(lái)合理泻轰,但是自我賦值出現(xiàn)時(shí)并不安全:
Widget& Widget::operator= ( const Widget& p)
{
delete q;
q = new Base(*p.q);
return *this;
}
這里的自我賦值的問(wèn)題是,operator=函數(shù)內(nèi)的*this和p有可能是同一個(gè)對(duì)象且轨。在函數(shù)末尾浮声,Widget中,它原本不該被自我賦值的動(dòng)作改變的旋奢,因?yàn)榘l(fā)現(xiàn)自己有一個(gè)指針指向一個(gè)已經(jīng)被刪除的對(duì)象泳挥。
為了阻止這種自我賦值的錯(cuò)誤,一般做法是operator=函數(shù)加一個(gè)“證同測(cè)試”至朗,來(lái)達(dá)到“自我賦值”的檢驗(yàn)?zāi)康模?/p>
Widget& Widget::operator= ( const Widget& p)
{
if(this == &p) ?return *this;
delete q;
q = new Base(*p.q);
return *this;
}