【C++基礎 02】深拷貝和淺拷貝

我的主題是,每天積累一點點。

===========================================


在類定義中,如果沒有提供自己的拷貝構造函數,則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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章