c++-深拷貝與淺拷貝

淺拷貝:只是將值原樣賦值給新的對象中的成員變量。如果類中涉及到內存動態分配就會出錯

深拷貝:先開闢空間,然後再賦值

默認的拷貝構造函數是淺拷貝,只是逐個賦值

先看一個例子,觀察淺拷貝能出現什麼問題:

#include <iostream>
#include <string.h>
using namespace std;

class String
{
private:
	char *str_;
public:
	String(char *str="")
	{
		int len = strlen(str)+1;
		str_ = new char[len];
		memset(str_,0,len);   //將str_內存地址的前len個位置設置爲0
		strcpy(str_,str);
	}

	~String()
	{
		delete []str_;
	}

	void display()
	{
		cout<<str_<<endl;
	}

};
int main()
{
	String s("ABC");
	s.display();
	//String s2 = s;    //調用的是默認的拷貝構造函數,實施的是淺拷貝
	                  //等價於s2.str_ = s.str_ 逐個賦值
	                  //兩者指向同一個內存,在程序退出時調用析構函數,同一塊內存被釋放了兩次,因此出錯

	return 0;
}
對上述的問題解決方案:重寫拷貝構造函數,使其指向兩個不同的內存空間

代碼如下:

	String(const String &other)
	{
		int len = strlen(other.str_)+1;
		str_ = new char[len];
		memset(str_,0,len);
		strcpy(str_,other.str_);
	}
接下來看下面代碼是怎麼執行的:

	String s3;
	//s3 = s;               //error  調用的是=運算符,系統提供的默認等號運算符也是淺拷貝
解決方案就是重寫=運算符:

	String &operator=(const String &other)
	{
		if(this == &other)
		{
			return *this;
		}
		//否則的話就銷燬以前已經存在的空間
		delete[] str_;
		int len = strlen(other.str_)+1;
		str_ = new char[len];
		memset(str_,0,len);
		strcpy(str_,other.str_);
	}

這裏這是爲了介紹深拷貝與淺拷貝,其實最終的問題是出在析構函數中的delete處,可以根據自己的需要來修改。

有些對象是唯一的獨一無二的,是不能拷貝和賦值的,可以將拷貝構造函數和=運算符函數放到私有函數中,並且不提供實現(不提供實現是爲了只要調用這兩個函數時在編譯階段就會報錯)。達到禁止拷貝的效果。




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