引用计数写时拷贝

本文介绍了引用计数和写时拷贝的概念,以解决浅拷贝和深拷贝的问题。引用计数在创建对象时初始化为1,拷贝构造函数递增计数,析构函数和赋值运算符分别递减计数,当计数为0时释放空间。写时拷贝在对象内容改变时进行深拷贝,否则进行浅拷贝。文章分析了String类的写时拷贝实现方案,探讨了两种不同的实现方法及其优缺点。
摘要由CSDN通过智能技术生成

浅拷贝是值拷贝,由之前深拷贝分析的文章知,浅拷贝后,两个指针指向同一空间。容易出现多次释放同一空间的问题,以及修改其中一个指针指向的内容影响其他指针指向的内容的问题。而深拷贝效率低,每次对对象进行值和空间同时拷贝,但这样会存开辟很多空间。为了避免产生更多的空间,引入写时拷贝,当对空间进行更改时,检查是否有除了自己以外的对象使用该块空间,若有,则自己重新开辟空间进行改正,不影响其他对象;若没有其他对象使用此空间,则说明只有自己使用此空间,直接进行更改。此时引用计数用来统计有多少对象使用此空间,克服了浅拷贝和深拷贝存在的问题。

void TestString()
{
    String s1;
    for(size_t i=0;i<1000000;i++)
    {
       String s2(s1);//此处的拷贝构造为深拷贝时,程序会崩溃
    }
}

一、分析写时拷贝。
1、引用计数的工作方式
1)除了初始化对象外,每个构造函数(拷贝构造函数除外)要建立一个引用计数,用来记录多少对象与正在创建的对象为共享一块内存空间。当我们创建一个对象时,只有一个对象用该空间,故将引用计数初始化为1。
2)拷贝构造函数不分配新的计数器,而是拷贝数据成员,包括计数器。拷贝构造递增计数器,指出给定的对象的内存空间被一个新的用户共用。
3)析构函数递减计数器,指出共用空间的用户少了一个,如果计数器为0,则释放该空间。
4)赋值运算符重载,递增右侧运算对象的计数器,递减左侧运算对象的计数器。如果左侧运算对象的计数器为0,就要对该对象进行销毁。
2、写时拷贝
写时拷贝在写的时候(即改变对象内容时)才会真正的开辟空间拷贝(深拷贝),如果只是对数据进行读,只会对数据进行浅拷贝。
写时拷贝:引用计数器的浅拷贝,又称延时拷贝,写时拷贝技术是通过“引用计数”实现的,在分配空间的时候多分配4或8个字节,用来记录有多少指针指向该空间,当有新指针指向这块空间时,引用计数加1。当要释放该块空间时,引用计数减1,直到引用计数减为0才释放掉该块空间。当有的指针要改变这块空间的值时,再为这个指针分配自己的空间(此时,引用计数的变化,旧空间的引用计数减1,新分配的空间的引用计数加1)。

二、完成写时拷贝的各种方案。
1、分析以下String的copy on write的几种实现方案哪种可以?为什么?
这里写图片描述

//方案1
class string
{
private:
    char* _str;
    int _refcount;
}

//方案1实现
class String
{
  public:
       String(char* str=" ")
          :_refCount(0)
       {
          _str=new char[strlen(str)+1];
          strcpy(_str,str);
          _refCount++;
       }
       String(String &s)
           :_refCount(s._refCount)
       {
           _str=s._str;
           _refCount++;
           s._refCount=_refCount;
           //这里虽然可以让两个对象的_refCount相等,但
           //如果超出两个对象的_str指针都指向同一块内存时,
           //就无法让所有对象的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值