String类 (浅拷贝/深拷贝/写时拷贝)

来源:互联网 发布:ipad看图软件 编辑:程序博客网 时间:2024/06/05 01:01

浅拷贝是指当对象的字段值被拷贝时,字段引用的对象不会被拷贝。例如,如果一个对象有一个指向字符串的字段,并且我们对该对象做了一个浅拷贝,那么两个对象将引用同一个字符串。

存在问题:
如果源程序中没有显示定义拷贝构造函数,在进行对象的拷贝时,将调用系统默认的拷贝构造函数,这就使得两个对象指向了同一资源,而析构函数又在对象生命周期结束后可以释放空间,势必会两次返还空间,编译器就会报错。

这时就需要用到深拷贝了。

深拷贝的两种版本:

#define  _CRT_SECURE_NO_WARNINGS 1  #include<iostream>using namespace std;//#if 0class String{public:    String(char *pStr = "")   //构造函数    {        if (NULL == pStr)        {            _pStr = new char[1];            *_pStr = 0;        }        else        {            _pStr = new char[strlen(pStr) + 1];            strcpy(_pStr, pStr);        }    }    //简洁版    ////拷贝构造函数 1    //String(const String &s)    //  :_pStr(new char[strlen(s._pStr) + 1])    //{    //  String temp(s._pStr);    //  swap(_pStr, temp._pStr);    //}    ////拷贝构造函数 2    //String(const String &s)    //  :_pStr(NULL)    //{    //  _pStr = new char[1];    //  String temp(s._pStr);    //  swap(_pStr, temp._pStr);    //}    //普通版    String(const String &s)        :_pStr(new char[strlen(s._pStr) + 1])    {        strcpy(_pStr, s._pStr);    }    //赋值运算符重载     /*    //由于pTemp在栈上,出了函数将销毁,故错误    String &operator=(const String &s)//赋值运算符重载    {    if (this != &s)    {    char *pTemp = new char[strlen(s._pStr) + 1];//  pTemp在栈上    strcpy_s(pTemp, strlen(s._pStr), s._pStr);    //strcpy_s(_pStr, strlen(pStr), pStr);    delete[] _pStr;    _pStr = pTemp;    }    return *this;    }    */    //赋值运算符重载 1    /*    String &operator=(const String &s)    {    //if (this != &s)   赋值运算符重载的反例,会造成一块空间多次释放    //{    //  _pStr = s._pStr;    //}    //return *this;    if (this != &s)    {    String temp(s._pStr);//用S里面的字符串构造一个临时的temp    swap(_pStr, temp._pStr);//交换两个指针    }    return *this;    }    */    //赋值运算符重载 2    String& operator=(const String& pStr)    {        if (this != &pStr)        {            //防止new开辟内存失败,丢失原来内存              char* ptr = new char[strlen(pStr._pStr) + 1];            strcpy(ptr, pStr._pStr);            delete[]_pStr;            _pStr = ptr;        }        return *this;    }    ~String()    //析构函数    {        if (this != NULL)        {            delete[] _pStr;            _pStr = NULL;//可有可无        }    }    friend ostream& operator<<(ostream & _cout, const String&pStr);private:    char *_pStr;};//输出流重载ostream& operator<<(ostream & _cout, const String&pStr){    _cout << pStr._pStr << endl;    return _cout;}void FunTest1(){    String s1("hello");    cout << "s1=" << s1 << endl;    String s2(s1);   //调用拷贝构造函数    cout << "s2=" << s2 << endl;}void FunTest2(){    String s3("word");    String s4;    s4 = s3;         //调用赋值运算符重载    cout << "s3=" << s3 << endl;    cout << "s4=" << s4 << endl;}int main(){    FunTest1();    FunTest2();    getchar();    return 0;}//#endif

这里写图片描述

1、开辟两个空间的计数,代码如下:

#include<iostream>using namespace std;class String{public:    String(const char * pStr = "")//构造函数        :_pCount(new int(1))  //_pCount初始化为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;//调用一次拷贝构造函数_pCount++    }    //赋值运算符重载    String & operator = (const String & s)    {        if (this != &s)        {            if (0 == --*_pCount)            {                delete[] _pStr;                delete _pCount;            }            _pStr = s._pStr;            _pCount = s._pCount;            ++*_pCount;        }    }    ~String()//调用析构函数时 先--_pCount,判断是否为0    {        if ((_pStr) && (0 == --*_pCount))        {            delete[] _pStr;            _pStr = NULL;            delete _pCount;            _pCount = NULL;        }    }    friend ostream& operator<<(ostream & output, const String &s);private:    char * _pStr;    int * _pCount;};ostream& operator<<(ostream & output, const String &s)//输出流的重载{    output << s._pStr << endl;    return output;}void FunTest(){    String s1("hello");    cout << "s1=" << s1 << endl;    String s2(s1);    cout << "s2=" << s2 << endl;    String s3("heihei");    cout << "s3=" << s3 << endl;    String s4 = s3;    cout << "s4=" << s4 << endl;}int main(){    FunTest();    getchar();    return 0;}

运行结果:
_pCount计数

2、一个空间的计数,代码如下:

class String//{//public://  String(char* ptr = NULL)//  {//      if (ptr == NULL)//      {//          _ptr = new char[5];//          *(_ptr + 4) = 0;//      }//      else//      {//          _ptr = new char[strlen(ptr) + 5];//          strcpy(_ptr + 4, ptr);//      }//      *(int*)_ptr = 1;//  }//  String(const String& s)//      :_ptr(s._ptr)//  {//      (*(int*)_ptr)++;//  }//  String& operator=(const String& s)//  {//      if (&s != this)//      {//          _ptr = s._ptr;//          (*(int*)_ptr)++;//      }//      return *this;//  }//  ~String()//  {//      if (--*(int*)_ptr == 0)//      {//          delete[] _ptr;//          _ptr = NULL;//      }//  }//private://  char* _ptr;//};class String{public:    String(const char* pStr)    {        if (pStr == NULL)            pStr = " ";        _pStr = new char[strlen(pStr) + 1 + 4];//多开辟4个字节        _pStr += 4;        strcpy(_pStr, pStr);        GetReference() = 1;    }    String(const String&s)        :_pStr(s._pStr)    {        ++ GetReference();    }    String & operator = (const String & s)    {        if (this != &s)        {            if (--GetReference() = 0)            {                _pStr -= 4;                delete[] _pStr;            }            _pStr = s._pStr;            ++GetReference();        }    }    ~String()    {        if ((--GetReference() == 0) && _pStr)        {            _pStr -= 4;            delete[] _pStr;            _pStr = NULL;        }    }    friend ostream & operator<<(ostream &output, String &s);private:    int& GetReference()    {        return *(int*)(_pStr - 4);    }    char* _pStr;};ostream & operator<<(ostream &output, String &s){    output << s._pStr << endl;    return output;}void FunTest(){    String s1("ximenchuixue");    cout << "s1=" << s1 << endl;    String s2(s1);    cout << "s2=" << s2 << endl;    String s3("sikongzhaixing");    cout << "s3=" << s3 << endl;    String s4 = s3;    cout << "s4=" << s4 << endl;}int main(){    FunTest();    getchar();    return 0;}

运行结果:

阅读全文
1 0
原创粉丝点击