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时,进行分离

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