我的主題是,每天積累一點點。
===========================================
在類定義中,如果沒有提供自己的拷貝構造函數,則C++提供一個默認拷貝構造函數。
C++提供的默認拷貝構造函數的工作方法是:完成一個成員一個成員的拷貝。如果成員是類對象,則調用其拷貝構造函數或者默認拷貝構造函數。需要注意的是,默認拷貝構造函數不會處理靜態成員變量。
簡單的自定義拷貝構造函數:
class Student{
public:
//拷貝構造函數
Student(Student& s)
{
a = s.a;
}
protected:
int a;
};
如上,我們拷貝的策略是一個一個成員的拷貝,但是如果一個類擁有資源,當其構造函數分配了一個資源(如堆內存),而拷貝構造函數沒有去分配該資源,那麼兩個對象都擁有同一個資源,這稱爲淺拷貝。
淺拷貝的一個問題是,當對象析構的時候,該資源將經歷兩次資源返還。比如下面這樣子:
class Person
{
public:
Person(char* pN)
{
cout<<"Constructing"<<pN<<endl;
pName = new char[strlen(pN) + 1];
if(pName != 0)
{
strcpy(pName,pN);
}
}
~Person()
{
cout<<"Destructing"<<pName<<endl;
delete pName;
pName = NULL;
}
protected:
char* pName;
};
void main()
{
Person p1("fzll");
Person p2 = p1; //調用默認拷貝函數
}
//輸出信息
Constructing fzll
Destructing fzll
Destructing
Null pointer assignment
可以看到,第二次釋放資源的時候,出錯了。因爲默認拷貝構造函數並沒有分配新的資源。
所以我們需要自定義拷貝構造函數,並分配資源,使拷貝和被拷貝的對象指向不同的資源,這就是深拷貝的概念。C++提供的默認拷貝構造函數就是淺拷貝。
具體如下:
class Person
{
public:
Person(char* pN)
{
cout<<"Constructing"<<pN<<endl;
pName = new char[strlen(pN) + 1];
if(pName != 0)
{
strcpy(pName,pN);
}
}
Person(Person& p)
{
cout<<"CopyPerson "<<p.pName<<endl;
pName = new char[strlen(p.pName) + 1];
if(pName != 0)
{
strcpy(pName,p.pName);
}
}
~Person()
{
cout<<"Destructing"<<pName<<endl;
delete pName;
pName = NULL;
}
protected:
char* pName;
};
void main()
{
Person p1("fzll");
Person p2 = p1; //調用自定義拷貝函數
}
//輸出信息
Constructing fzll
CopyPerson fzll
Destructing fzll
Destructing fzll
堆內存是最常用的需要構造拷貝的資源,還有其它資源,比如文件的打開,設備的佔有(如打印機)服務業需要深拷貝。
一個很好的經驗是:如果你的類需要析構函數來釋放資源,那麼它也需要一個拷貝構造函數(深拷貝的方式)。
==============================================================
轉載請註明出處:http://blog.csdn.net/shun_fzll/article/details/37774495