写时拷贝

来源:互联网 发布:火箭炮 知乎 编辑:程序博客网 时间:2024/06/04 19:15

1.写时拷贝的定义:

       由于浅拷贝使多个对象共用一块内存地址,调用析构函数时导致一块内存被多次释放,导致程序奔溃。

       写时拷贝,就是在写的时候(即改变字符串的时候)才会真正开辟空间(深拷贝),如果只对数据读取时,就对数据进行浅拷贝,也称写时拷贝。

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



2. string中的两种写时拷贝


#include<iostream>  #include<stdlib.h>  using namespace std;  class String  {  public:       String(char *str = "")        :_str(new char[strlen(str) + 5])       {            *(int *)_str = 1;            _str += 4;            strcpy(_str, str);       }       ~String()       {            if (_str != NULL)            {                _Release();            }       }       String(const String& str)       {            _str = str._str;            ++_GetRefCount();       }       String& operator=(const String& str)       {            if (this != &str)            {                 _Release();                 _str = str._str;                 ++ _GetRefCount();            }            return *this;       }       char& operator[](int index)//写时拷贝       {               if (_GetRefCount()>1)//当引用次数大于1时新开辟内存空间            {                 --_GetRefCount();//原来得空间引用计数器减1                 char *str = new char[strlen(_str) + 5];                 strcpy(str+4, _str);                 _str = str+4;                 _GetRefCount()++;            }            return _str[index];       }       friend ostream& operator<<(ostream& output, const String& str)       {            output << str._str;            return output;       }     private:       int& _GetRefCount()       {            return *(int *)(_str - 4);       }       void _Release()       {            if (--_GetRefCount() == 0)            {                 delete[] (_str-4);            }       }  private:       char *_str;  };  




原创粉丝点击