浅いコピーを解決するいくつかの方法

17214 ワード

ライブラリ関数の操作の熟練した把握は非常に重要であり、今日私が実現したのは、その浅いコピー、深いコピー、およびカウントバージョンを参照するMyStringを含む簡潔なバージョンのMyStringです.一.単純な浅いコピー、すなわち値コピーであり、入出力演算子の再ロードを含む.
//   ,    
class MyString
{
    friend ostream& operator<str);  //          
    friend istream& operator>>(istream& is,MyString& str);
public:
    MyString(const char *str="")    //        ,         
        :_str(new char[strlen(str)+1])
    {
        strcpy(_str,str);
    }
    MyString(const MyString& str)  //         
        :_str(str._str)
    {}
    MyString& operator=(const MyString& str)
    {
        if(this != &str)
        {
            _str=str._str;
        }
        return *this;
    }
    ~MyString()
    {
        if(_str)
        {
            delete[]_str;
        }
    }
private:
    char *_str;
};
ostream& operator<str)
{
    os<<str._str;
    return os;
}
istream& operator>>(istream& is,MyString& str)
{
    is>>str._str;
    return is;
}

void TestMyString()
{
    MyString str("hello str");
    MyString strCopy("hello DataCopy");
    MyString strTmp(strCopy);    //      
    cout<str;
    cout<//              ,error
};

二.深いコピーは、上で実装した浅いコピーバージョンのMyStringでは簡単な値コピー、つまり複数のポインタが同じ空間を指す場合があり、この場合、この空間を解析する際に問題が発生します.同じ空間では複数回解析することは許されないからです.深いコピー浅いコピー問題を解決するには、コピー構造や付与演算子の再ロード時にも、ポインタが指す空間をコピーしなければならない.このとき、ポインタが1つの空間を指し、解析時にはもちろん問題は発生しない.
//   
class MyString
{
    friend ostream& operator<public:
    MyString(const char *str="")
        :_size(strlen(str))
        ,_capacity(strlen(str)+1)
        ,_str(new char[_capacity])
    {
        cout<<"MyString()"<strcpy(_str,str);
    }
    MyString(const MyString& ps)     //   
        :_size(ps._size)
        ,_capacity(strlen(ps._str)+1)
        ,_str(new char[_capacity])
    {
        cout<<"MyString(const MyString& ps)"<strcpy(_str,ps._str);
    }
    //MyString& operator=(MyString& ps)
    //{
    //  cout<
    //  if(this != &ps)
    //  {
    //      delete[]_str;
    //      _str=new char[strlen(ps._str)+1];
    //      strcpy(_str,ps._str);
    //  }
    //  return *this;
    //}
    //     ,                  
    MyString& operator=(MyString ps)
    {
        cout<<"MyString& operator=(MyString& ps)"<std::swap(_str,ps._str);
        std::swap(_size,ps._size);
        std::swap(_capacity,ps._capacity);
        return *this;
    }
    ~MyString()
    {
        cout<<"~MyString()"<if(_str)
        {
            delete[]_str;
            _str=NULL;
            _size=0;
            _capacity=0;
        }
    }
private:
    int _size;     //     
    int _capacity; //     
    char *_str;
};

ostream& operator<return os;
}

void TestMyString()
{
    MyString str("hello str");
    MyString strCopy("hello DeapthCopy");
    MyString strTmp(strCopy);
    cout<cout<

三.リファレンスカウント-書き込み時コピー浅いコピーの問題を解決する際にポインタが指す空間の内容をコピーする方法は、スペースを浪費します.もし私たちが空間を残して、空間を指すポインタの個数を表すことができれば、新しいポインタがこの空間を指すカウンタがあれば+1、ある読者は疑問を抱くかもしれません.これは浅いコピーの考え方と同じではないでしょうか.解析中に問題は発生しませんか?確かに、しかしカウントを参照する構造関数の中でこのポインタが最後の空間を指すポインタでない限り、私たちはそのカウンタを1減らして、さもなくばやっとこの空間を分析します;第1版の参照カウントでは、浅いコピーの問題を解決します.
//      MyString
class MyString
{
    friend ostream& operator<str);
public:
    MyString(const char *str="")
        :_str(new char[strlen(str)+1+4])   //   4                 
    {
        cout<<"  "<_str += 4;
        GetCount()=1;    //         1
        strcpy(_str,str);
    }
    MyString(const MyString& str)
        :_str(str._str)
    {
        cout<<"    "<char& operator[](size_t index)    //       
    {
        cout<<"operator[]"<assert(index > 0 && index < strlen(_str));
        if(GetCount() > 1)
        {
            --GetCount();
            char *tmp=new char[strlen(_str)+5];
            strcpy(tmp+4,_str);
            Delete();
            _str=tmp+4;
            GetCount()=1;
        }
        return _str[index];
    }
    MyString& operator=(MyString& str)
    {
        cout<<"operator="<if(this != &str)
        {
            if(--GetCount() == 0)
            {
                Delete();
            }
            ++str.GetCount();
            _str=str._str;
        }
        return *this;
    }
    ~MyString()
    {
        cout<<"  "<if(--GetCount() == 0)
        {
            cout<<"  "<int& GetCount()         //       
    {
        return *(int *)(_str-4);
    }
    void Delete()         //    ,             
    {
        delete[](_str-4);
    }
private:
    char *_str;
};
ostream& operator<str)
{
    os<<str._str;
    return os;
}

void TestMyString()
{
    MyString str("hello str");
    MyString strCopy("hello ReCount");
    MyString strTmp(str);
    cout<5]='-';
    cout<

第2版の参照カウントは、浅いコピーの問題を解決します.このバージョンは、ある空間を指すポインタの個数を格納するために整形された空間を再割り当てし、前のバージョンは、ある空間を指すポインタの個数を格納するために4バイトの空間を直接多く開いています.
class MyString
{
    friend ostream& operator<public:
    MyString(const char *str="")
        :_str(new char[strlen(str)+1])
        ,_pCount(new int[sizeof(int)])
    {
        cout<<"  "<1;
        strcpy(_str,str);
    }
    MyString(const MyString& str)
        :_str(str._str)
        ,_pCount(str._pCount)
    {
        cout<<"    "<operator=(MyString& str)
    {
        if(this != &str)
        {
            if(--GetCount() == 0)   //               
            {
                Delete();
            }
            str.GetCount()++;
            _str=str._str;
            _pCount=str._pCount;
        }
        return *this;
    }
    char& operator[](size_t index)
    {
        cout<<"operator[]"< 0 && index < strlen(_str));
        if(GetCount() > 1)
        {
            --GetCount();
            //                    
            char *tmpChar=new char[strlen(_str)+1];
            int *tmpInt=new int[sizeof(int)];
            strcpy(tmpChar,_str);
            *tmpInt=*_pCount;
            Delete();     //  this    _str __pCount
            _str=tmpChar;
            _pCount=tmpInt;
            GetCount()=1;
        }
        return _str[index];
    }
    ~MyString()
    {
        cout<<"  "<if(--GetCount() == 0)
        {
            cout<<"  "<private:
    int& GetCount()
    {
        return *_pCount;
    }
    void Delete()
    {
        delete[]_str;
        delete[]_pCount;
    }
private:
    char *_str;
    int *_pCount;
};
ostream& operator<return os;
}

void TestMyString()
{
    MyString str("hello str");
    MyString strCopy("hello ReCount");
    MyString strTmp(strCopy);
    cout<//hello ReCount
    strTmp=str;
    cout<//hello str-->str strTmp strCopy
    strCopy=str;
    strTmp[5]='-';
    cout<

ここでシェア終了~~~