写时拷贝——string类

浅拷贝使多个对象共用一块内存地址,调用析构函数时导致一块内存被多次释放,导致程序奔溃。实现string类的时候通常显示的定义拷贝构造函数和运算符重载函数。

在我们在不需要写,只是读的时候就可以不用新开辟内存空间,就用浅拷贝的方式创建对象,当我们需要写的时候才去新开辟内存空间。这种就是写时拷贝。在构造函数中开辟新的空间时多开辟4个字节的空间,放在内存单元首部,用来存放引用计数器,记录这快空间的引用次数。
 

#include <iostream>
using namespace std;
#include <string.h>
class String{
public:
	String(char*str=null)
	{
		ptr=(char*)malloc(strlen(str)+1+4);
		*(int*)ptr=1;
		ptr+=4;
		strcpy(ptr,str);
	}

	~String()
	{
		if(ptr!=NULL)
			_Realease();
	}

	String(const String&rhs)
	{
		ptr=rhs.ptr;
		++(*(int*)(ptr-4));
	}

	String& operator=(const String&rhs)
	{
		if(this!=&rhs)
		{
			_Realease();
			ptr=rhs.ptr;
			++(*(int*)(ptr-4));
		}
		return *this;
	}
	
        char& operator[](int index)//写时拷贝  
        {     
          if (*(int*)(ptr-4)>1)//当引用次数大于1时新开辟内存空间  
          {  
      	      --*(int*)(ptr-4);//原来的空间引用计数器减1  
              char *str = (char*)malloc(strlen(ptr) + 5);  
              strcpy(str+4, ptr);  
              str+=4;  
              (*(int*)(str-4))++;//新开辟内存引用计数加一  
          }  
          return ptr[index];  
         }

        friend ostream& operator<<(ostream& output, const String& str)  
        {  
              output << str.ptr;  
              return output;  
        } 
private:
	 char*ptr;

	void _Realease()//减引用计数
	{
		int count=*(int*)(ptr-4);
		if((--count)==0)
		{
			free(ptr-4);
			ptr=NULL;
		}
	}
};

int main()
{
	String str1("lkd251");

	String str2(str1);

	String str3=str1;

	String str4("sddefsdfrv2e2e2r3");

	std::cout<<str1<<" "<<str4[4]<<std::endl; //lkd251     k
	return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值