c++---模拟实现String类(浅拷贝)

更多点子:c++—目录索引(知识小渠道)


String:浅拷贝之引用计数+写时拷贝

浅拷贝:当类里面有指针对象时,进行简单赋值的浅拷贝,两个对象指向同一块内存,析构时delete两次这块内存,存在崩溃问题,这时得进行深拷贝
深拷贝:(String s2=s1)构造s2时拷贝一块跟s1指向数据块一样大的数据块,并将值拷贝下来,这样s1和s2指向各自的数据块,析构时delete各自的数据块

写时拷贝还是建立在浅拷贝上的,新变量和原来的共用一块数据,引用计数+1,如果谁需要变化,就重新开辟一块空间,把数据给考过来,然后在上面修改怎么样的,如果没有修改的就不用再开辟空间,只是将计数器+1,赚到

引用计数+写时拷贝
_PCount(计数器是成员变量)

namespace COW//copy on write
{
    class String
    {
    public:
        String(const char* str = "")
            :_str(new char[strlen(str) + 1])
            , _pCount(new int(1))
        {
            strcpy(_str, str);
        }
        String( const String& s)
            :_str(s._str)
            , _pCount(s._pCount)
        {
            (*_pCount)++;
        }
        //s1= s3
        String& operator=(const String& s)
        {
            if (&s != this)
            {
                /*if (--(*_pCount) == 0)
                {
                delete[] _str;
                delete _pCount;
                }*/
                Release();
                _str = s._str;
                _pCount = s._pCount;
                ++(*_pCount);
            }
            return *this;
        }
        void CopyOnWrite()//凡是可能会写(改变)的接口,就调这个函数
        {
            if (*_pCount > 1)//说明这段空间不是一个人独占的,那我就得重新弄一个
            {
                char* newstr = new char[strlen(_str) + 1];
                strcpy(newstr, _str);
                _str = newstr;
                --(*_pCount);
                _pCount = new int(1);//新开辟出来的空间,引用计数为1
            }
        }
        /*void Insert(size_t pos, const char* str)
        {
            CopyOnWrite();
            ...
        }*/
        char& operator[](size_t pos)//读的时候也可能会修改,不如调CopyOnWrite先期完成
        {
            CopyOnWrite();
            return _str[pos];
        }
        const char& operator[](size_t pos)const
        {
            return _str[pos];
        }
        const char* c_str()
        {
            return _str;
        }
        void Release()//并不是真的释放,是检查引用计数
        {
            if (--(*_pCount) == 0)
            {
                delete[] _str;
                delete _pCount;
                _str = NULL;
                _pCount = NULL;
            }
        }
        ~String()
        {
            Release();
        }
    private:
        char* _str;
        int* _pCount;
    };
}

引用计数+写时拷贝
计数器在字符串开头前4个字节

class String
{
public:
    String(const char* str = "")
        :_str(new char[strlen(str)+5])
    {
        _str += 4;
        strcpy(_str, str);
        //*((int*)(_str - 4)) = 1;
        GetRefCount() = 1;
    }
    //s2(s1)
    String(const String& s)
        :_str(s._str)
    {
        ++GetRefCount();
    }
    //s1=s2
    String& operator=(const String& s)
    {
        if (this != &s)
        {
            this->Release();
            _str = s._str;
            ++GetRefCount();
        }
        return *this;
    }
    int& GetRefCount()
    {
        return *((int*)(_str - 4));
    }
    void Release()
    {
        if (--GetRefCount() == 0)
        {
            delete[](_str - 4);
        }
    }
    void CopyOnWrite()
    {
        if (GetRefCount() > 1)
        {
            char* newstr = new char[strlen(_str) + 5];
            newstr += 4;
            strcpy(newstr, _str);
            --GetRefCount();//这儿指的是原来的计数
            _str = newstr;
            GetRefCount() = 1;//这儿是后来新的计数
        }
    }
    char& operator[](size_t pos)
    {
        CopyOnWrite();
        return _str[pos];
    }
    ~String()
    {
        Release();
    }
private:
    char* _str;
};

如果有什么不对的地方,可以评论告诉我,望指导!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值