写时拷贝

上篇博客http://blog.csdn.net/xiaodu655/article/details/78148833浅谈了浅拷贝与深拷贝,说明了浅拷贝存在的问题,下面就针对浅拷贝存在的问题给出了以下的解决方案—-引用计数。
以下为两个空间的计数:
这里写图片描述
具体的实现如下:

class String    //两个空间计数
{
public:
    String(const char*str = "") //构造函数
     :_count(new int(1))
        {
            if (NULL == str)
            {
                _str = new char[1];
                *_str = '\0';
            }
            else
                _str = new char[strlen(str) + 1];
            strcpy(_str, str);
        }
    String(const String&d) //计数
        :_str(d._str)
        , _count(d._count)
    {
        ++*_count;
    }
    String &operator=(const String&d) //赋值运算符
    {                                         
        if (this != &d)
        {
            if (--*_count == 0)
            {
                delete[]_str;
                delete _count;
            }
            _str = d._str;
            _count = d._count;
            ++*_count;
        }
    }
    ~String()
    {
        if (_str&&--*_count == 0)
        {
            delete[] _str;
            _str = NULL;
         delete[]_count;
         _count = NULL;
        }

    }
private:
    char*_str;
  int* _count;//若给成静态的则其会成为全局的,程序会出现错误
};

写时拷贝如下图所示:这里写图片描述
即为只开辟一块空间,但是会给引用计数开四个字节,具体的实现如下:

class String
{
public:
    String(const char*str = "")
    {
        if (str == NULL)
            str = "";
        _str= new char[strlen(str) + 1 + 4];  //多开辟四个字节用来计数
        _str += 4;//_str真正的位置
        strcpy(_str, str);
        *(int*)(_str - 4) = 1;//因为指针已经向后偏了四个字节
    }
    String(const String&s)
        :_str(s._str)
    {
        ++GetReference();
    }
    String&operator=(const String&s)
    {
        if (this != &s)
        {
            Release();
            _str = s._str;
            ++GetReference();
        }
        return *this;
    }
    char &operator[](size_t idx)
    {
        //if ((idx > 0) && (idx < strlen(_str)))
        if (GetReference() > 1)//GetReference()>1说明这块空间至少两个人在用          
        {
            //--GetReference();//如果执行这一步将会多减掉一个空间
            String str(_str);
            swap(_str, str._str);
        }
        return _str[idx];
    }
    ~String()
    {
        Release();
        _str = NULL;

    }
    friend ostream&operator<<(ostream&_cout, String&d);
    friend istream&operator>>(istream&_cin, String&d);
private:
    int &GetReference()  //引用计数。这段空间为堆上的空间,不受影响
    {
        return *(int*)(_str - 4);
    }
    void Release()
    {
        if (_str && (--GetReference() == 0))
        {
            _str -= 4;
            delete[]_str;
        }
    }
    char* _str;
};
ostream &operator<<(ostream&cout, String&d)
{
    cout << d._str;
    return cout;
}
istream&operator>>(istream&cin, String&d)
{
    char str[20];
    cin >> str;
    d = str;
    return cin;
}
void Test()
{
    char str[] = "hello";
    str[0] = 'p';
    cout << str << endl;
    String c1("hello");
    c1[0] = 'n';
    cout << c1 << endl;
    String c2(c1);
    cout << c2 << endl;
    String c3;
    c3 = c2;
    c1[0] = 'n';//若上边函数不是传引用则其无法作为左值
    cout << c3 << endl;
    cout << c3[2] << endl;
}
int main()
{
    Test();
    system("pause");
    return 0;
}

测试结果如下所示:
这里写图片描述
本人是新手,希望大家多多给予建议。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值