C/C++ — 写时拷贝

写时拷贝

_______________________________________________________



何为写时拷贝? 前面我说过深拷贝浅拷贝,今天我们来探究一下写时拷贝。 深拷贝是补充了浅 拷贝的不足,写时拷贝其实也

就是补充一点深拷贝的不 足。 其实写时拷贝的意思就是: 当你读 取到这个空间的时候,并不会开辟出一个一 模一样 的空间出

来给你,当你真正需要拷贝的时候,那 么他就会开辟出空间 给你。 也就是拖延版的深拷贝。





写时拷贝技术是通过"引用计数"实现的,在分配空间的时候多分配4个字节,用来记录有多少个指针 指向块空间,当有新的指
针指向这块空间时,引用 计数加一,当要释放这块空间时,引用计数减一 (假装释放),直到引用计数减为0时才真的释放掉这
块空间。当有的指针要改变这块空间的值时,再 为这个指针分配自己的空间(注意这时引用计数的变化,旧的空间的引用计数
减一,新分配的空间引 用计数加一)。






写时拷贝的实用:实现一个string类

class String  
{  
public:  
    String(const char *str = "")  
        :_str(new char[strlen(str) + 1 + 4])  
    {  
        cout << "Sring()" << endl;  
        _str += 4;                            //前4个字节用来存放引用计数  
        GetCount() = 1;                       //引用计数的初始值设置成1  
        strcpy(_str, str);  
    }  
  
    String(String& s)  
        :_str(s._str)  
    {  
        cout << "Sring(String&)" << endl;  
        GetCount()++;  
    }  
  
    String& operator=(String& s)  
    {  
        cout << "Sring& operator=" << endl;  
  
        if (this != &s)  
        {  
            Release();  
            _str = s._str;  
            GetCount()++;  
        }  
        return *this;  
    }  
  
    ~String()  
    {  
        cout << "~Sring()" << endl;  
        Release();  
    }  
public:  
    char& operator[](size_t index)  
    {  
        if (GetCount() == 1)                   //如果计数器为1,则直接返回  
        {  
            return _str[index];  
        }  
        GetCount()--;  
        char *tmp = _str;  
        _str = new char[strlen(tmp) + 1 + 4];  
        _str += 4;  
        strcpy(_str, tmp);  
        GetCount() = 1;  
        return _str[index];  
    }  
private:  
    int& GetCount()  
    {  
        return *(int *)(_str - 4);  
    }  
    void Release()  
    {  
        if (--GetCount() == 0)  
        {  
            cout << "释放" << endl;  
            delete[](_str - 4);        //注意释放的时候还有 存放引用计数的4个字节  
            _str = NULL;  
        }  
    }  
private:  
    char *_str;  
};

这里有一个问题呢~,C++标准的确就是这样的,C++标准认为,当你通过迭代器或[]获取到string的内部 地址的时候,string

并不知道你将是要读还是 要写。这是它无法确定,为此,当你获取到内部引用后,为 了避免不能捕获你的写操作,它在此时废

止了写时才拷贝技术。 这样看来我们在使用写时拷贝的时候,一定要注意,如果你不需要对string的内部进行修改,那你就千

不要使 用通过[]操作符和迭代器去获取字符串 的内部地址引用,如果你一定要这么做,那么你就必须要付 出代价。 当然,

string还提供了一些使迭代器和引用失效的方法。比如说push_back,等,  你在使用[]之 后再使用 迭代器之后,引用就有可能失效了。


这个博客有部分借鉴了我的学长~ 
  
他的博客链接:http://blog.csdn.net/lf_2016/article/details/52354838
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值