寫時拷貝(方案三)

方案三

class String
{
    private:
               char* _str;
               size_t  _size;
               size_t  _capacity;
               int* _refCount;       //***
};


方案三設置了一個int型的指針變量用來引用計數,每份內存空間對應一個引用計數,而不是每個對象對應一個引用計數,而且每塊內存的引用計數互不影響,不會出現方案一和方案二出現的問題。

wKioL1b02FLwCu7hAABgAKEPIVU082.png



1.在實現賦值運算符重載要謹慎,不要遇到下圖的情形

wKiom1b01-3hnH92AAA27Q6gKJQ921.png


2.改變字符串的某個字符時要謹慎,不要遇到類似下圖所遇到的問題。

如果多個對象都指向同一塊內存,那麼只要一個對象改變了這塊內存的內容,那所有的對象都被改變了!!

wKioL1b02LDzSancAAA2uD01zzw105.png

可以用下圖的形式改善這種問題:新設置一塊內存來存要改變的對象

wKiom1b02DjTpQ8kAAApO8D-1x4083.png

案例3我畫的圖較多,方便大家結合代碼去理解 

class String
{
public:
	String(char* str = "")    //不能strlen(NULL)
	{
		_refCount = new int(1);     //給_refCount開闢空間,並賦初值1
		_size = strlen(str);
		_capacity = _size + 1;
		_str = new char[strlen(str) + 1];
		strcpy(_str, str);
	}
	String(const String &s)
	{
		_refCount = s._refCount;
		_str = s._str;
		_size = strlen(s._str);
		_capacity = _size + 1;
		(*_refCount)++;      //拷貝一次_refCount都要加1
		
	}
	
	//要考慮是s1=s2時,s1原先不爲空的情況,要先釋放原內存
	//如果要釋放原內存時,要考慮它的_refCount減1後是否爲0,爲零再釋放,否則其它對象指針無法再訪問這片空間
	String& operator=(String& s)  
	{
		if (_str!= s._str)
		{
			_size = strlen(s._str);
			_capacity = _size + 1;
			if (--(*_refCount) == 0)
			{
				delete[] _str;
				delete _refCount;
			}
			
			_str = s._str;
			_refCount = s._refCount;
			(*_refCount)++;
		}		
		return *this;
	}
	//如果修改了字符串的內容,那所有指向這塊內存的對象指針的內容間接被改變
	//如果還有其它指針指向這塊內存,我們可以從堆上重新開闢一塊內存空間,
	//把原字符串拷貝過來
	//再去改變它的內容,就不會產生鏈式反應
	//  1.減引用計數  2.拷貝   3.創建新的引用計數
	char& String::operator[](const size_t index) //參考深拷貝      
	{
		if (*_refCount==1)
		{
			return *(_str + index);
		}
		else
		{
			--(*_refCount);
			char* tmp = new char[strlen(_str)+1];
			strcpy(tmp, _str);
			_str = tmp;
			_refCount = new int(1);
			return *(_str+index);
		}
	}
	~String()
	{
		if (--(*_refCount)== 0)  //當_refCount=0的時候就釋放內存
		{
			delete[] _str;
			delete _refCount;
			_str = NULL;
			cout << "~String " << endl;
		}
		_size = 0;
		_capacity = 0;
	}
private:
    char* _str;      //指向字符串的指針
    size_t  _size;      //字符串大小
    size_t  _capacity;   //容量
    int* _refCount;    //計數指針
};

以下是其它方案鏈接地址:

方案一:

http://iynu17.blog.51cto.com/10734157/1755179

方案二:

http://iynu17.blog.51cto.com/10734157/1755185

方案四:(推薦)

http://iynu17.blog.51cto.com/10734157/1755213



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