【c++】深浅拷贝,引用计数写时拷贝

来源:互联网 发布:java伪代码怎么写 编辑:程序博客网 时间:2024/05/20 07:18

什么是浅拷贝?
例如下面的代码,:

class AA{private:    int* _a = new int[2];};int main(void){    AA a1;    AA a2(a1);    system("pause");    return 0;}

这里写图片描述
我们看到对象a1和a2地址一样,指向同一块空间
这里写图片描述
当类中的成员变量包括指针时,而又没有定义自己的拷贝构造函数,那么在拷贝一个对象的情况下,就会调用其默认拷贝构造函数,其实这个函数没做什么事,只是对其成员变量作了个简单的拷贝,也就是所谓的位拷贝,它们指向的还是同一个存储空间,当对象析构时,就会析构多次!
这里写图片描述
深拷贝
深拷贝是为了解决浅拷贝中同一块空间多次释放的问题。
例如:

String(const String& str)    {        _str = new char[strlen(str._str) + 1];        strcpy(_str, str._str);    }

我们看到,this->_str拥有了属于自己的一块空间。
这里写图片描述
【深拷贝的现代写法】

String(const String& str)    {        _str = NULL;        String tmp(str._str);        swap(_str, tmp._str);    }

写时拷贝
何为写时拷贝??深拷贝是补充了浅拷贝的不足,写时拷贝其实也就是补充一点深拷贝的不足。其实写时拷贝的意思就是当你读取到这个空间的时候,并不会开辟出一个一模一样的空间出来给你,当你真正需要拷贝的时候,那么他就会开辟出空间给你。也就是拖延版的深拷贝。
这里写图片描述
写时拷贝代码

class String1{public:    String1(const char* str = "")//构造函数        :_str(new char[strlen(str) + 1])        , _refCount(new int(1))    {        strcpy(_str, str);    }    String1(String1& s)//拷贝构造        :_str(s._str)        , _refCount(s._refCount)    {        (*_refCount)++;    }    ~String1()//析构    {        if (--(*_refCount) == 0)//当_refCount=1时,说明该空间只属于一个对象,可以被释放了        {            delete[] _str;            delete _refCount;        }    }private:    char* _str;    int* _refCount;};

赋值运算符重载】要考虑多种情况:
这里写图片描述

String1& operator =(const String1& s)    {        if (_str != s._str)        {            if (--(*_refCount) == 0)            {                delete[] _str;                delete _refCount;            }            _str = s._str;            _refCount = s._refCount;            *(_refCount)++;        }        return *this;    }

写时拷贝

void CopyOnWrite()    {        if (*_refCount > 1)        {            char* newstr = new char[strlen(_str)];            strcpy(newstr, _str);            (*_refCount)--;            _str = newstr;            _refCount = new int(1);        }    }

第二种方式
开辟一个空间,前面4个字节为计数器count,剩下的为字符串_str的空间,用法与分开相同。
这里写图片描述

String(const char* str = " ")      :_str(new char[strlen(str)+5]{     strcpy(_str+4,str);     *((int*)_str) = 1;     _str += 4;}String(const String & s)      :_str(s._str){     (*(int*)(_str-4))++;}~String(){     if(--*((int*)(_str-4))==0)     {     delete[](_str-4);     }}String & operator = (const String & s){   if(_str != s.s_str)   {   if(--GetRefCount() == 0)   {      delete[] (_str-4);   }   _str = s.s_str;   GetRefCount()++;   }   return *this;}int& GetRefCount(){    return (*(int *)(_str-4));}
原创粉丝点击