[cpp]
view plain copy#include<iostream.h>
#include<string.h>
//淺拷貝例子 沒有自己寫復(fù)制構(gòu)造函數(shù)而是采用默認(rèn)的復(fù)制構(gòu)造函數(shù)
class name
{ public :
name(char *pn) ;
~ name() ;
protected :
char *pname ;
int size ;
} ;
name :: name(char *pn)
{
cout <<" Constructing " << pn << endl ;
pname = new char[strlen(pn)+1] ;
if (pname!=0)
strcpy(pname,pn) ;
size = strlen(pn) ;
}
name :: ~ name()
{
cout << " Destructing " << pname << endl ;
pname[0] = '\0' ;
delete []pname ;
size = 0 ;
}
void main()
{
name Obj1("NoName") ;
name Obj2 = Obj1 ;
}
創(chuàng)建Obj1對象時,開辟內(nèi)存空間存放數(shù)據(jù),而執(zhí)行到 name Obj2 = Obj1 語句時,將Obj1對象復(fù)制給Obj2對象,因為沒有構(gòu)造拷貝構(gòu)造函數(shù),因此調(diào)用默認(rèn)的拷貝構(gòu)造函數(shù),只是進(jìn)行了淺拷貝
將Obj2對象指向Obj1對象的內(nèi)存空間,而Obj2對象沒有自身的內(nèi)存空間,當(dāng)程序調(diào)用Obj2對象的析構(gòu)函數(shù)時,釋放了其指向的內(nèi)存空間即Obj1對象開辟的內(nèi)存空間。而當(dāng)Obj1對象析構(gòu)時,因為Obj2對象已經(jīng)將其內(nèi)存空間析構(gòu)掉了,所以程序執(zhí)行到此處將崩潰掉。
解決淺拷貝帶來的問題的方法就是:重新構(gòu)造一個拷貝構(gòu)造函數(shù),在函數(shù)中重新開辟一段內(nèi)存空間為Obj2對象所用。
[cpp]
view plain copyname::name(const name &Obj)
{
cout << " Copying " << Obj.pname << " into its own block\n" ;
pname = new char[strlen(Obj.pname)+1] ;
if (pname!=0)
strcpy(pname, Obj.pname) ;
size = Obj.size ;
}
[cpp]
view plain copy/*
接著上一步之后又重新創(chuàng)建了一個Obj3對象并采用等號運算符賦值給Obj2(注意:此時是先創(chuàng)建Obj3對象,兩條語句賦值)
*/
void main()
{
name Obj1("NoName") ;
name Obj2 = Obj1 ;
name Obj3("obj3...");
//重載=號操作符
Obj2 = Obj3; //=號操作
}
程序執(zhí)行完此name Obj2 = Obj1 后 ,Obj1與Obj2由于調(diào)用了自己寫的構(gòu)造函數(shù)因此,Obj1與Obj2都有自己的內(nèi)存空間,然后程序繼續(xù)執(zhí)行,創(chuàng)建Obj3對象,分配內(nèi)存空間,
而執(zhí)行到Obj2 = Obj3語句時,因為是等號運算符,編譯器會調(diào)用默認(rèn)的拷貝構(gòu)造函數(shù),進(jìn)行了淺拷貝,產(chǎn)生了與上面的同樣的問題,Obj2 與Obj3指向了統(tǒng)一內(nèi)存空間。使程序崩潰。
解決等號運算符與淺拷貝帶來的問題的方法就是:重載等號運算符,在函數(shù)中重新開辟一段內(nèi)存空間為Obj2對象所用,但是由于之前Obj2已經(jīng)開辟了內(nèi)存空間為了防止內(nèi)存泄露,需要先對內(nèi)存空間進(jìn)行釋放,然后在重建新的內(nèi)存空間。
[cpp]
view plain copyvoid name::operator=(Name &obj3)
{
if (pname != NULL)
{
delete []pname;
pname = NULL;
size = 0;
}
cout<<"測試有沒有調(diào)用我。。。。"<<endl;
pname = new char[strlen(Obj.pname)+1] ;
if (pname!=0)
strcpy(pname, Obj.pname) ;
size = Obj.size ;
}