【c++】深浅拷贝,引用计数写时拷贝

什么是浅拷贝?
例如下面的代码,:

class AA
{

private:
    int* _a = new int[2];
};

int main(void)
{
    AA a1;
    AA a2(a1);
    system("pause");
    return 0;
}

这里写图片描述
我们看到对象a1和a2地址一样,指向同一块空间
这里写图片描述
当类中的成员变量包括指针时,而又没有定义自己的拷贝构造函数,那么在拷贝一个对象的情况下,就会调用其默认拷贝构造函数,其实这个函数没做什么事,只是对其成员变量作了个简单的拷贝,也就是所谓的位拷贝,它们指向的还是同一个存储空间,当对象析构时,就会析构多次!
这里写图片描述
深拷贝
深拷贝是为了解决浅拷贝中同一块空间多次释放的问题。
例如:

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

我们看到,this->_str拥有了属于自己的一块空间。
这里写图片描述
【深拷贝的现代写法】

String(const String& str)
    {
        _str = NULL;
        String tmp(str._str);
        swap(_str, tmp._str);
    }

写时拷贝
何为写时拷贝??深拷贝是补充了浅拷贝的不足,写时拷贝其实也就是补充一点深拷贝的不足。其实写时拷贝的意思就是当你读取到这个空间的时候,并不会开辟出一个一模一样的空间出来给你,当你真正需要拷贝的时候,那么他就会开辟出空间给你。也就是拖延版的深拷贝。
这里写图片描述
写时拷贝代码

class String1
{
public:
    String1(const char* str = "")//构造函数
        :_str(new char[strlen(str) + 1])
        , _refCount(new int(1))
    {
        strcpy(_str, str);
    }
    String1(String1& s)//拷贝构造
        :_str(s._str)
        , _refCount(s._refCount)
    {
        (*_refCount)++;
    }
    ~String1()//析构
    {
        if (--(*_refCount) == 0)//当_refCount=1时,说明该空间只属于一个对象,可以被释放了
        {
            delete[] _str;
            delete _refCount;
        }
    }
private:
    char* _str;
    int* _refCount;
};

赋值运算符重载】要考虑多种情况:
这里写图片描述

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

写时拷贝

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

第二种方式
开辟一个空间,前面4个字节为计数器count,剩下的为字符串_str的空间,用法与分开相同。
这里写图片描述

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));
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值