string类的写时拷贝与引用计数

由于浅拷贝使多个对象共用一块内存地址,调用析构函数时导致一块内存被多次释放,导致程序奔溃。

实现string类的时候通常显示的定义拷贝构造函数和运算符重载函数。

由于释放内存空间,开辟内存空间时花费时间,因此,在我们不需要写,只是读的时候就可以不用新开辟内存空间,就用浅拷贝的方式创建对象,当我们需要写的时候才去新开辟内存空间。

这种方法就是写时拷贝。在构造函数中开辟新的空间时多开辟4个字节的空间,用来存放引用计数器,记录这快空间的引用次数。

这里写图片描述

#include<iostream>    
#include<stdlib.h>    
using namespace std;    
class String    
{    
public:    
     String(char *str = "")    
      :_str(new char[strlen(str) + 5])    
     {    
          *(int *)_str = 1;    
          _str += 4;    
          strcpy(_str, str);    
     }    
     ~String()    
     {    
          if (_str != NULL)    
          {    
              _Release();    
          }    
     }    
     String(const String& str)    
     {    
          _str = str._str;    
          ++_GetRefCount();    
     }    
     String& operator=(const String& str)    
     {    
          if (this != &str)    
          {    
               _Release();    
               _str = str._str;    
               ++ _GetRefCount();    
          }    
          return *this;    
     }    
     char& operator[](int index)//写时拷贝    
     {    

          if (_GetRefCount()>1)//当引用次数大于1时新开辟内存空间    
          {    
               --_GetRefCount();//原来得空间引用计数器减1    
               char *str = new char[strlen(_str) + 5];    
               strcpy(str+4, _str);    
               _str = str+4;    
               _GetRefCount()++;    
          }    
          return _str[index];    
     }    
     friend ostream& operator<<(ostream& output, const String& str)    
     {    
          output << str._str;    
          return output;    
     }    

private:    
     int& _GetRefCount()    
     {    
          return *(int *)(_str - 4);    
     }    
     void _Release()    
     {    
          if (--_GetRefCount() == 0)    
          {    
               delete[] (_str-4);    
          }    
     }    
private:    
     char *_str;    
};    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值