string基礎模擬實現深淺拷貝

string實現

  1. string(const char* str)
  2. string(string&string)
  3. operator=(string &string)
  4. ~string()
    爲什麼要有深拷貝?

淺拷貝

又稱爲位拷貝,是將資源按位拷貝,如果對象中管理資源,最後就會導致多個對象共享同一份資源,當一個對象銷燬時就會將該資源釋放掉,而此時另一些對象不知道該資源已經被釋放,造成重複釋放,例如

char c[] = "ada";
char *d = c;

因此有了深拷貝

#include <iostream>
#include <string>
#include <algorithm>
#pragma warning(disable:4996)
using namespace std;
namespace bit
{
	class string
	{
	public:
		string(const char*  str= "")
		{
			if (str == nullptr)
			{
				_str = new char[1];
				(*_str) = '\0';
			}
			else
			{
				_str = new char[strlen(str)+1];
				strcpy(_str, str);
			}
			
		}
		string(const string& S)
		{
			_str = new char[strlen(S._str) + 1];
			strcpy(_str,S._str);
		
		}
		
		string& operator=(const string& S)
		{
			//if (&S !=  this)
			//{
			//	
			//	
			//	char*_pstr = new char[strlen(S._str) + 1];
			//	delete[] _str;//釋放字符串用delete[]
			//	strcpy(_pstr, S._str);
			//	_str = _pstr;
			//	return *this;//舊時
			//}
			string strtmp(S);
			swap(strtmp._str, _str);//新型
			return *this;
		}

		~string()
		{
			if (_str)
			{
				delete[] _str;
				_str = nullptr;
			}
		}
	private:

		char* _str;
	};


}

int main()
{
	bit::string a("hello world");
	bit::string b(a);
	bit::string c;
	c = a;
	b = a;
	
}

對於 a,b,c 每份資源都是獨立的因此不會造成重複釋放同一塊資源。

有沒有辦法使得淺拷貝也能防止資源的重複釋放?
可以參考智能指針,用一個標記確定當前有多少指針指向這個資源,當該標記爲0時,釋放該資源。
對於這個標記,可能有兩種方法能實現,一個是設置一個靜態變量 count ,第二個是設置一個int指針變量count。每有一個指針指向資源,使其+1.再考慮到某些情況,放棄第一種方案,有興趣的讀者可以想一想爲什麼?


namespace bit
{
	class string
	{
	public:
		string(const char* str = "")
		{
			if (str == nullptr)
			{
				_str = new char[1];
				(*_str) = '\0';

			}
			else
			{
				_str = new char[strlen(str) + 1];
				strcpy(_str, str);
			}
			*count = 1;
		}
		string(const string& S)
		{
			if (_str != nullptr && --(*count) == 0)
			{
				delete[] _str;
				delete count;
				_str = nullptr;
				count = nullptr;
			}
			_str = S._str;
			count = S.count;
			(*count)++;
			//cout << *count;

		}

		string& operator=(const string& S)
		{
			if (_str != nullptr && --(*count) == 0)
			{
				delete[] _str;
				delete count;
				_str = nullptr;
				count = nullptr;
			}
			_str = S._str;
			count = S.count;
			(*count)++;//不能*count++,
			
			return *this;
		}
		char& operator[](int i)
		{
			if (*count > 1)//?爲什麼大於1
			{
				bit::string S(_str);
				Swap(S);
			}
			return _str[i];
		}

		char& operator[](int i) const
		{
			return _str[i];
		}

		~string()
		{
			if (_str && --(*count) == 0)
			{
				delete[] _str;
				delete count;
				_str = nullptr;
				count = nullptr;
			}
		}
		void Swap(bit::string S)
		{
			swap(_str,S._str);
			swap(count, S.count);

		}
	private:

		char* _str;
		int* count = new int(0);
	};


}

但是上面的代碼有一個很大的缺陷,當對於其中一個資源進行修改,會影響其他的資源,因此我們可以在寫的時候將這份資源分離,也就是寫時拷貝,Copy On Write,對[]進行重載,當*count的值大於2時,進行分離

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