c++ string类深拷贝其他版本(简洁版,引用计数版,写时拷贝版)

简洁版:

class String
{
public:
	String(char* pStr="")
	{
          if(pStr==NULL)
	   {
	        _pStr=new char[0];
		_pStr='\0';
	   }
	   else
	   {
	        _pStr=new char[strlen(pStr)+1];
		 strcpy(_pStr,pStr);
	   }
	}
	String(const String& s)
	{
		String str(s._pStr);
		_pStr=NULL;
		std::swap(_pStr,str._pStr);
	}
	String& operator=(const String& s)
	{
		String str(s._pStr);
		std::swap(_pStr,str._pStr);
	 
	    return *this;
	}
	
	~String()
	{
	         delete[] _pStr;
		  _pStr=NULL;
	  
	}

private:
	char* _pStr;
};

引用计数版

    思路:成员变量除了_pStr,再引入一个计数_pCount的。调用构造函数时,将分配的内存标记为1,(表明有1人在使用)。
            相应地,调用拷贝构造函数,赋值操作时,每调用一次,_pCount+1,表明使用这段空间的人又多了一个。
            同理,在析构函数中,每调用一次,_pCount-1,直到无人使用时,方可删除。
   对象模型如下图
                      
class String
{
public:
	String(char* pStr=""):_pCount(new int(1))//调用一次构造函数,引用计数加1
       {
	 if(pStr==NULL)
	 {
	   _pStr=new char[0];
	   _pStr='\0';
	 }
	 else
	 {
	  _pStr=new char[strlen(pStr)+1];
	  strcpy(_pStr,pStr);
	 }
	
	}

	String(const String& s):_pStr(s._pStr),_pCount(s._pCount)//每调用一次拷贝构造函数,引用计数加1
	{
	 ++(*_pCount);
	}

    String& operator=(const String& s)
	{
	 if(this!=&s)
	 {
	   if(0==--(*_pCount))//只有一个人用的话,删除这段空间
	   {
	       delete[] _pStr;
	       _pStr=NULL;
	       delete _pCount;
	      _pCount=NULL;
	   }
	   _pStr=s._pStr;
	   _pCount=s._pCount;
	   ++(*_pCount);//引用计数加1
	 }
	 return *this;
	}

	~String()
	{
		if(0==--(*_pCount) && _pCount)//引用计数为1时,方可删除这段空间
		{
			delete[] _pStr;
	       _pStr=NULL;
	       delete _pCount;
	      _pCount=NULL;

		}
	}
private:
	char* _pStr;
	int* _pCount;
};



写时拷贝

思路:成员变量依旧只有一个char* _pStr,但是用_pStr指向空间的前四个字节来存放同时使用该空间的个数。
        所以,调用构造函数时,开辟的空间要多4字节,_pStr需要向后+4,再存放内容,要向前四字节内放入1,表示此时该空间有一人使用。
                 调用拷贝构造函数和赋值操作时,原理同上面的引用计数相同,需要增加前四字节的值。
                 调用析构函数时,注意“引用计数”(即前四字节的数)为空时,方可删除,此时,删除前,要将_pStr-4,即将刚多申请的四字节内存一并删去。

对象模型如下图:


class String
{
public:

	String(char* pStr="")
	{
	   if(pStr==NULL)
	   {
	     _pStr=new char[1+4];
		 _pStr+=4;
		 *_pStr='\0';
	   }
	   else
	   {
	        _pStr=new char[strlen(pStr)+1+4];//多申请4字节
		_pStr+=4;//往后移动4字节
               strcpy(_pStr,pStr);//拷贝内容
	   }
            GetCount()=1;//计数为1
	}
	String(const String& s):_pStr(s._pStr)
	{
	   ++GetCount();//每次调用计数+1
	}
	String& operator=(const String& s)
	{
	  Release();//释放原来的空间
	  _pStr=s._pStr;
	  ++GetCount();//每次调用计数+1
	  return *this;
	}
	~String()
	{
	 Release();
	}

	char& operator[](size_t index)
	{
	  if(GetCount()>1)//当该空间和别人公用时
	  {
		char* temp=new char[strlen(_pStr)+1+4];//重新开辟空间
		temp+=4;
		strcpy(temp,_pStr);
	        --GetCount();//原来的计数减1
		_pStr=temp;
		GetCount()=1;//重新开辟的空间计数为1
	  }
	  return _pStr[index];
	}
	int& GetCount()//获取计数器次数
	{
		return *((int*)_pStr-1);//将_pStr转为int*,再减1,表明向前移动了4字节。
	}
	void Release()//释放空间
	{
	 if(0==--GetCount())//只用1人使用时,可以删除
	 {
	   _pStr-=4;//指针向前移4字节(删除计数的4字节)
	   delete[] _pStr;
	   _pStr=NULL;
	 }
	}
private:
	char* _pStr;
};


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值