[C++]深拷贝与浅拷贝

浅拷贝定义:

浅拷贝,指的是在对象复制时,只是对对象中的数据成员进行简单的复制,默认拷贝构造函数执行的也是浅拷贝。简单的说,浅拷贝就是值传递,将源空间里面的内容复制到目标空间中。
缺陷:多个指针可能共用管理一块内存空间,在释放时,导致对一块空间的多次释放,造成内存泄露。

深拷贝定义:

在“深拷贝”的情况下,对于对象中动态成员,就不能仅仅简单地赋值了,而应该重新动态分配空间。

浅拷贝实现

include<iostream>
using namespace std;
class String
{
    public :
      String(const char*pStr="")
        {
          if(NULL==pStr)
            {
                _pStr=new char[1];
                *_pStr='\0';
                }
        else 
        {
             _pStr=new char[strlen(pStr)+1];
             strcpy(_pStr,pStr);
        }
            }
    String(const String& s)
            :_pStr(s._pStr)
        {    

            } 
    String& operator=(const String& s)
    {
        if(this!=&s)
        {
            _pStr=s._pStr;
        }
    return *this;
    }
~String ()
{
  if(_pStr)
   {
      delete[] _pStr;
        _pStr=NULL;         
     }
}
private: 
    char* _pStr;

};
void FunTest()
{
    String s1("hello");
    String s2(s1);
    String s3;
    s3=s1;
}

int main ()
{
    FunTest();
    String s1("hello");
    String s2(s1);
    String s3(NULL);
    String s4(s1);
    s3=s4;
    s3=s1;
    return 0;
}

完成深拷贝

引入引用计数:指示当前空间有多少指针指向该空间.
注意:用计数可以普通的成员变量,引用计数不可以为普通的成员变量,因为一旦出了作用域,该空间被销毁,达不到想要的效果.因此可以采用private类型的static型变量.

#include<iostream>
using namespace std;
class String
{
public :

    String(const char* pStr="")
        :_pCount(new int (1))
    {
        if(NULL==pStr)
        {
            _pStr=new char[1];
            *_pStr='\0';
        }
        else 
        {
            _pStr=new char[strlen(pStr)+1];
             strcpy(_pStr,pStr);
        }
    }
String (const String& s)
    :_pStr(s._pStr)
    ,_pCount(s._pCount)

   {
       ++(*_pCount);
      }

String& operator=(const String& s)
{
    if(_pStr!=s._pStr)
    {
        if(_pStr&&0==--*_pCount)
        {
            delete [] _pStr;
            delete _pCount;
        }
        _pStr =s._pStr;
        _pCount=s._pCount;
        ++_pCount;
    }
    return *this;
}
~String ()
{
    if(_pStr&&(0==--*_pCount))
    {
        delete[] _pStr;
        _pStr=NULL;
        delete _pCount;
        _pCount=NULL;
    }
}
private: 
    char* _pStr;
     int* _pCount;
};
void FunTest()
{
    String s1("hello");
    String s2(s1);
    String s3;
    s3=s2;
}
int main()
{
    FunTest();
    return 0;
}

写时拷贝

写时拷贝:如果要朝当前对象写东西,建议使用这种方式,且单线程不会有问题

#include<iostream>
using namespace std;
class String
{
public :
    String(const char* pStr="")
    {
        if(NULL==pStr)
        {
            _pStr=new char[1+4];
            _pStr+=4;
            *_pStr='\0';
        }
        else 
        {
            _pStr=new char[strlen(pStr)+1+4];
            _pStr+=4;
             strcpy(_pStr,pStr);
        }
        GetRaf()=1;
    }
String (const String& s)
    :_pStr(s._pStr)


   {
       GetRaf()++;
      }

String& operator=(const String& s)
{
    if(_pStr!=s._pStr)
    {
        Release();
        _pStr =s._pStr;
        ++GetRaf();
    }

    return *this;
}

~String ()
{
    Release();
}

char& operator [] (size_t index)
{
    if(GetRaf()>1)
    {
        char* pTemp=new char [strlen(_pStr)+1+4];
        *(int*)pTemp=1;
        pTemp+=4;
        strcpy(pTemp,_pStr);
        --GetRaf();
        _pStr=pTemp;
    }
        return _pStr[index];
}
const char& operator [](size_t index)const 
{
    return _pStr[index];
}
private:
    int& GetRaf()
    {
            return *((int*)_pStr-1);
    }
    void Release()
    {
        if(_pStr&&(0==--GetRaf()))
            {
            _pStr-=4;
            delete[] _pStr;
            _pStr=NULL;
            }

    }
private: 
    char* _pStr;
};

void FunTest()
{
    String s1("hello");
    String s2(s1);
    s2[0]='w';
    String s3;
    s3=s2;
}

int main()
{
    FunTest();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值