C++——写时拷贝

深浅拷贝中提到的深浅拷贝也有自己的缺陷。我们知道浅拷贝可能造成重新出错,深拷贝又会浪费空间。因为并不是每个要拷贝的对象都会修改数据,如果并不准备修改数据,浅拷贝进行读也是可以的。所以就有了写时拷贝。它具体实现思想是:先对原始对象进行浅拷贝,若是要修改数据就再调用深拷贝,让它修改自己的数据,不会造成原始对象受到影响的情况。
我们将写时拷贝认为是使用引用计数实现的浅拷贝。我们在开辟空间时会多开辟4字节用以保存引用技术pcount的值。在有其他对象需要这块内存时,pcount++,在有对象析构时,pcount–。直至只有一个对象指向这块内存,在这个对象使用完之后,我们就可以真正的free这块堆上分配的内存。
具体实现代码如下:

class String
{
    public:                                                                                                                                           
        //构造函数
        String(const char* str = "") 
        {   
            _str = new char[strlen(str)+1];
            strcpy(_str, str);
            _pcount = new int(1);
        }   

        //s2(s1)
        String(const String& s)//浅拷贝构造
        {   
            _str = s._str;
            _pcount = s._pcount;
            ++(*_pcount);
        }   

        //s1 = s2
        String& operator=(const String& s)//赋值运算符
        {   
            //if(this != &s)
            if(_str != s._str)
            {   
                if(--(*_pcount) == 0)
                {   
                    delete[] _str;
                    delete _pcount;
                }   
                _str = s._str;
                _pcount = s._pcount;
                ++(*_pcount);
            }
            return *this;
        }

        ~String()//析构函数
        {
            //要保证当前对象是唯一一个使用它的,才可以释放内存
            if(--(*_pcount) == 0)
            {
                delete[] _str;
                delete _pcount;
            }
        }

        void CopyOnWrite()//写时拷贝
        {
            if(*_pcount > 1)
            {
                char* tmp = new char[strlen(_str)+1];
                strcpy(tmp, _str);
                --(*_pcount);

                _str = tmp;
                _pcount = new int(1);
            }
        }

        char& operator[](size_t pos)//重载[]
        {
            CopyOnWrite();                                                                                                                            
            return _str[pos];
        }

        const char& operator[](size_t pos) const
        {
            return _str[pos];
        }

        char* c_str()
        {
            return _str;
        }

    private:
        char* _str;
        //引用计数要实现内存共享,所以它应该是在堆上的数据,每个对象都有一个指向它的指针
        int* _pcount;//引用计数,使用int*可以使其指向同一块空间,否则只有一个对象能看到当前的引用计数
        size_t _size;
        size_t _capacity;
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值