C++編譯器會(huì)為每個(gè)類自動(dòng)生成一個(gè)默認(rèn)的構(gòu)造函數(shù)、析構(gòu)函數(shù)、賦值函數(shù)、拷貝構(gòu)造函數(shù),這當(dāng)然是在你沒有為你的類聲明這些函數(shù)的時(shí)候。這些默認(rèn)的功能函數(shù)在為你提供方便的時(shí)候,也會(huì)給你帶來麻煩。
例如:
class string {
public:
string(const char *value);
~string();
... // 沒有拷貝構(gòu)造函數(shù)和operator=
private:
char *data;
};
string::string(const char *value)
{
if (value) {
data = new char[strlen(value) + 1];
strcpy(data, value);
}
else {
data = new char[1];
*data = '\0';
}
}
inline string::~string() { delete [] data; } //注意:new 和delete 要采用相同的形式。
如果有string的兩個(gè)對(duì)象,
string a("hello");
string b("world");
當(dāng)b=a時(shí),因?yàn)槟阕约簺]為類定義那些函數(shù),所以C++編譯器會(huì)提供默認(rèn)的賦值函數(shù),這個(gè)缺省的賦值操作符會(huì)執(zhí)行從a的成員到b的成員的逐個(gè)成員的賦值操作,對(duì)指針(a.data和b.data) 來說就是逐位拷貝。這種情況下至少有兩個(gè)問題。
第一,b曾指向的內(nèi)存永遠(yuǎn)不會(huì)被刪除,因而會(huì)永遠(yuǎn)丟失。這是產(chǎn)生內(nèi)存泄漏的典型例子。
第二,現(xiàn)在a和b包含的指針指向同一個(gè)字符串,那么只要其中一個(gè)離開了它的生存空間,其析構(gòu)函數(shù)就會(huì)刪除掉另一個(gè)指針還指向的那塊內(nèi)存,重復(fù)析構(gòu)的問題。
下面的語句:
string a("hello"); // 定義并構(gòu)造 a
{ // 開一個(gè)新的生存空間
string b("world"); // 定義并構(gòu)造 b
...
b = a; // 執(zhí)行 operator=, 調(diào)用默認(rèn)賦值函數(shù)
// 丟失b的內(nèi)存,造成內(nèi)存泄露。
} // 離開生存空間, 調(diào)用
// b的析構(gòu)函數(shù)
string c = a; // c.data 的值不能確定! 調(diào)用默認(rèn)的拷貝構(gòu)造函數(shù)
// 但是a.data 已被刪除,無法進(jìn)行拷貝構(gòu)造。
當(dāng)這類對(duì)象進(jìn)行函數(shù)參數(shù)按值傳遞時(shí),形參會(huì)按照缺省的拷貝構(gòu)造函數(shù)進(jìn)行初始化,形參擁有一個(gè)指向該對(duì)象指針的一個(gè)拷貝,當(dāng)函數(shù)結(jié)束時(shí),形參會(huì)調(diào)用析構(gòu)函數(shù),該對(duì)象的指針也被銷毀。
class stack
{
public:
stack(const char *value);
~stack();
char * data;
};
stack::stack(const char *value)
{
if(value)
{
data= new char[strlen(value)+1];
strcpy(data,value);
}
else
{
data= new char[1];
*data = '\0';
}
}
inline stack::~stack()
{
delete []data;
}
void dosth(stack pstk)
{
cout<<pstk.data<<endl;
}
int main()
{
stack str("iamxczhang");
dosth(str);
}
在析構(gòu)函數(shù)出設(shè)立斷點(diǎn),你會(huì)看到析構(gòu)函數(shù)執(zhí)行兩次!
牢記:只要類里有指針變量就得自己寫拷貝構(gòu)造函數(shù)和賦值函數(shù),但是你確定用不著這些函數(shù)時(shí),可以把這些函數(shù)做private聲明而不去實(shí)現(xiàn)它,這就防止了會(huì)有人去調(diào)用它們,也防止了編譯器去生成它們。