溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

c++淺拷貝以及淺拷貝的解決方案

發(fā)布時(shí)間:2020-07-07 18:20:27 來源:網(wǎng)絡(luò) 閱讀:292 作者:夢T醒 欄目:編程語言

淺拷貝:以string類為例
c++淺拷貝以及淺拷貝的解決方案 當(dāng)對一個(gè)已知對象進(jìn)行拷貝時(shí),編譯系統(tǒng)會自動調(diào)用一種構(gòu)造函數(shù) —— 拷貝構(gòu)造函數(shù),如果用戶未定義拷貝構(gòu)造函數(shù),則會調(diào)用默認(rèn)拷貝構(gòu)造函數(shù)。默認(rèn)拷貝構(gòu)造屬于淺拷貝,相當(dāng)于兩個(gè)指針變量指向了同一塊地址空間,調(diào)用析構(gòu)函數(shù)時(shí),會delete兩次,所以在第二次delete時(shí)會發(fā)生中斷(無法尋址地址)

//淺拷貝
class string
    {
    private:
        char* _str;
    public:
        string(char* str = "")//構(gòu)造函數(shù)
        {
            if (nullptr == str)
            {
                str = "";
            }
            _str = new char[strlen(str) + 1];
            strcpy(_str,str);
        }
        string(const string& s)//拷貝構(gòu)造
            :_str(s._str)
        {
        }
        string operator =(string& s)//賦值構(gòu)造
        {
            _str = s._str;
            return *this;
        }
        ~string()
        {
            if (_str)
            {
                delete _str;
                _str = nullptr;
            }
        }
    };

c++淺拷貝以及淺拷貝的解決方案
解決方案1.傳統(tǒng)深拷貝
在拷貝構(gòu)造中重新開辟空間,然后把被拷貝對象中的元素拷貝到新空間中

//缺點(diǎn):需要多次開辟空間,代碼冗余
//優(yōu)點(diǎn):可讀性高
class string
{
private:
    char* _str;
public:
    string(char* str = "")
    {
        if (str == nullptr)
        {
            str = "";
        }
        _str = new char[strlen(str) + 1];
        strcpy(_str,str);
    }
    string(const string& s)
        :_str(new char[strlen(s._str)+1])
    {
        strcpy(_str,s._str);
    }
    string& operator=(string& s)
    {
        if (this != &s)
        {
            char* temp = new char[strlen(s._str) + 1];
            strcpy(temp,s._str);
            delete _str;
            _str = temp;
        }
        return *this;
    }
    ~string()
    {
        if (_str)
        {
            delete _str;
            _str = nullptr;
        }
    }
};

解決方案2.精簡深拷貝
1.傳址,在方法中重新定義一個(gè)對象接受被拷貝對象元素,然后交換臨時(shí)對象和需要拷貝對象的地址
2.傳值,直接交換臨時(shí)對象和需要拷貝對象的地址

//優(yōu)點(diǎn):代碼高效    缺點(diǎn):可讀性不高
class string
    {
    private:
        char* _str;
    public:
        string(char* str="")
        {
            if (str == nullptr)
            {
                str = "";
            }
            _str = new char[strlen(str) + 1];
            strcpy(_str,str);
        }
        string(const string& s)
            :_str(nullptr)
        {
            string temp(s._str);
            swap(_str,temp._str);
        }
        /*string& operator=(const string& s)
        {
            if (this != &s)
            {
                string temp = s._str;
                swap(_str,temp._str);
            }
            return *this;
        }*/
        string& operator=(string s)//直接改變指向(傳值:臨時(shí)變量)
        {
            swap(_str,s._str);
            return *this;
        }
        ~string()
        {
            if (_str)
            {
                delete[] _str;
                _str = nullptr;
            }
        }
    };

解決方案3.淺拷貝+計(jì)數(shù)(相當(dāng)于出門時(shí),最后一個(gè)人才“關(guān)門”,進(jìn)出門的人進(jìn)行計(jì)數(shù)
計(jì)數(shù):定義一個(gè)成員_count,在普通構(gòu)造函數(shù)中直接初始化為1,而進(jìn)行拷貝構(gòu)造時(shí)判斷被拷貝對象的成員_count++,而需要拷貝對象的成員_count是否為0,(如果為0,則需要拷貝對象成員_count++,如果>0,則則需要拷貝對象成員_count--),最后析構(gòu)函數(shù)中對象_count成員為0時(shí),調(diào)用delete

class string
    {
    private :
        char* _str;
        int* _count;
    public :
        string(char* str="")
            : _count(new int(1))//調(diào)用普通構(gòu)造:_count初始化為1
            , _str(new char[strlen(str) + 1])
        {
            if (str == nullptr)
            {
                str = "";
            }

            strcpy(_str,str);
        }
        string(const string& s)
            :_str(s._str)
            , _count(s._count)
        {
            ++(*_count);
        }
        string operator=(string& s)
        {
            if (this != &s)
            {
                if (0 == --(*_count))
                {
                    delete[] _str;
                    delete _count;
                    _str = nullptr;
                    _count = nullptr;
                }
                _str = s._str;
                _count = s._count;
                ++(*_count);
            }
            return *this;
        }
        ~string()
        {
            if (_str&&0 == --(*_count))
            {
                delete[] _str;
                delete _count;
                _str = nullptr;
                _count = nullptr;
            }
        }
        char& operator[](size_t index)
        {
            if ((*_count) > 1)
            {
                string temp(_str);
                this->swap(temp);
            }
            return _str[index];
        }
        void swap(string& s)
        {
            std::swap(_str,s._str);
            std::swap(_count,s._count);
        }
        const char& operator[](size_t index)const
        {
            return _str[index];
        }
    };
向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI