【C++】深拷贝、浅拷贝和写时拷贝

大家首先来看一下下面这段代码:

void Test()
{
    int *p1 = new int[10];
    int *p2 = p1;
    delete[] p1;
    delete[] p2;
}

运行这段代码:
这里写图片描述
我们发现这段程序无法运行,经过测试我们发现,p1和p2指向同一块空间:
这里写图片描述
这就是我们所说的浅拷贝。
浅拷贝:也称位拷贝,编译器只是直接将指针的值拷贝过来,结果多个对象共用同一块内存,当一个对象将这块内存释放掉之后,另一些对象不知道该块空间已经还给了系统,以为还有效,所以在对这段内存进行操作的时候,发生了访问违规。
这里写图片描述
【深拷贝】
这里写图片描述
构造s2时拷贝一块跟s1指向数据块一样大的数据块,并将值拷贝下来,这样s1和s2指向各自的数据块,析构时释放各自的数据块。
String类实现深拷贝
普通写法:

String(const String& s)
{
    _str = new char[strlen(s.str)+1];
    strcpy(_str,s._str);
}

现代写法:

String(const String& s)
      :_str(NULL)
{
    String tmp(s._str);
    swap(_str,tmp._str);
}

【写时拷贝】
这里写图片描述

class String
{
  privatechar *_str;
  static int refCount;
}
int String::refCount=0;

如此定义一个静态变量,会存在下面一个问题:
这里写图片描述
我们可以采用下面的方式进行定义:

class String
{
public:
String(const char* str=" ")          //构造函数
      :_str(new char [strlen(str)+1])
      ,_refCount(new int(1))
{
    strcpy(_str,str);
}
String(String & s)             //拷贝构造
      :_str(s._str)
      ,_refCount(s._refCount)
{
      (*_refCount)++;
}
~String()                     //析构函数
{
    if(--(*refCount)==0)
    {
       delete[]  _str;
       delete _refCount;
     }
}
private:
   char *_str;
   int *_refCount;
};

赋值运算符的重载我们需要考虑以下几种情况:
这里写图片描述

String& operator = (const String& s)
{
      if(_str != s._str)
      {
           if(--(*_refCount)==0)
          {
            delete[] _str;
            delete _refCount;
          }
          _str = s._str;
          _refCount = s._refCount;
          (*refCount)++;
      }
      return *this;
}

写时拷贝

void CopyWrite()
{
     if(*refCount>1)
     {
        char* newStr = new char[strlen(_str)];
        strcpy(newStr,_str);
        (*_refCount)--;
        _str = newStr;
        _refCount = new int(1);
     }
}

第二种实现方式:
这里写图片描述

String(const char* str = " ")
      :_str(new char[strlen(str)+5]
{
     strcpy(_str+4,str);
     *((int*)_str) = 1;
     _str += 4;
}

String(const String & s)
      :_str(s._str)
{
     (*(int*)(_str-4))++;
}
~String()
{
     if(--*((int*)(_str-4))==0)
     {
     delete[](_str-4);
     }
}
String & operator = (const String & s)
{
   if(_str != s.s_str)
   {
   if(--GetRefCount() == 0)
   {
      delete[] (_str-4);
   }
   _str = s.s_str;
   GetRefCount()++;
   }
   return *this;
}
int& GetRefCount()
{
    return (*(int *)(_str-4));
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值