C++STL主要組件之String總結(jié)(第二部分深、淺拷貝問題以及賦值運(yùn)算符重載)

第一部分連接https://blog.51cto.com/14232799/2447326

創(chuàng)新互聯(lián)是一家朝氣蓬勃的網(wǎng)站建設(shè)公司。公司專注于為企業(yè)提供信息化建設(shè)解決方案。從事網(wǎng)站開發(fā),網(wǎng)站制作,網(wǎng)站設(shè)計(jì),網(wǎng)站模板,微信公眾號(hào)開發(fā),軟件開發(fā),微信小程序開發(fā),十多年建站對公路鉆孔機(jī)等多個(gè)行業(yè),擁有多年的網(wǎng)站營銷經(jīng)驗(yàn)。

二.String的模擬實(shí)現(xiàn)

在第一步之后緊接著的就該是模擬實(shí)現(xiàn)部分,這一部分主要是體現(xiàn)自己對第一部分的掌握情況。強(qiáng)烈推薦和我一樣在學(xué)習(xí)String的朋友們自己動(dòng)手實(shí)現(xiàn)一下。因?yàn)樵诿嬖囍校嬖嚬倏傁矚g讓我們自己來模擬實(shí)現(xiàn)string類。

自己來實(shí)現(xiàn)String最主要是實(shí)現(xiàn)String類的構(gòu)造、拷貝構(gòu)造、賦值運(yùn)算符重載(第一部分operator開頭的方法)以及析構(gòu)函數(shù)。

以下是我完成的基礎(chǔ)模擬實(shí)現(xiàn)

#include<iostream>
#include<assert.h>
using namespace std;

namespace self{
    class string{
    public:
        string(const char* s = " "){
            if (s == nullptr){
                assert(false);
                return;
            }
            _s = new char[strlen(s) + 1];
            strcpy(_s, s);
        }
        ~string(){
            if (_s){
                delete[] _s;
                _s = nullptr;
            }
        }
    private:
        char* _s;
    };
}
int main(){
    self::string k = "hello";
    self::string i("world");
    self::string m;
    //self::string l(k);
    return 0;
}

以上就是沒有重載賦值運(yùn)算符且沒有顯式定義拷貝構(gòu)造函數(shù)的string類模擬實(shí)現(xiàn)?;就暾哪M實(shí)現(xiàn)會(huì)在本篇文章的最后給出(當(dāng)然免不了有紕漏,若是發(fā)現(xiàn)請各位大佬提醒)
上面的代碼中的main函數(shù)中有一句注釋語句 //self::string l(k); 我將其注釋是因?yàn)槿绻尤脒@一句代碼程序就會(huì)運(yùn)行崩潰?。。?!
程序崩潰的原因是: 當(dāng)我們不去顯式定義拷貝構(gòu)造方法的時(shí)候,系統(tǒng)就會(huì)生成默認(rèn)的拷貝構(gòu)造函數(shù),這種拷貝構(gòu)造函數(shù)是一種淺拷貝,最終結(jié)果就是導(dǎo)致 對象l和對象k在共用同一塊內(nèi)存空??雌饋硭坪鯖]什么問題?
但是!當(dāng)函數(shù)結(jié)束時(shí),在調(diào)用析構(gòu)函數(shù)的操作上就會(huì)出現(xiàn)大問題。
原本的話,每一個(gè)對象都會(huì)調(diào)用一次析構(gòu)函數(shù)來清理自己占用的空間。但是當(dāng)兩個(gè)對象所占用的是同一塊空間時(shí),一個(gè)對象調(diào)用完析構(gòu)函數(shù)后另一個(gè)對象調(diào)用析構(gòu)函數(shù)的時(shí)候,就會(huì)生同一塊空間被釋放多次的程序錯(cuò)誤!從而引起程序崩潰!
所以說在以上這個(gè)的代碼中不可以使用拷貝構(gòu)造方法。這個(gè)問題也就引出了下一個(gè)要總結(jié)的部分:淺拷貝和深拷貝

三.淺拷貝和深拷貝

1.淺拷貝
此處只是給個(gè)定義:
淺拷貝:也稱位拷貝,編譯器只是將對象中的值拷貝過來。如果對象中管理資源,最后就會(huì)導(dǎo)致多個(gè)對象共享同一份資源,當(dāng)一個(gè)對象銷毀時(shí)就會(huì)將該資源釋放掉,而此時(shí)另一些對象不知道該資源已經(jīng)被釋放,以為還有效,所以 當(dāng)繼續(xù)對資源進(jìn)項(xiàng)操作時(shí),就會(huì)發(fā)生發(fā)生了訪問違規(guī)。所以要解決淺拷貝問C++中引入了深拷貝。
(第二部分的string模擬事先就是個(gè)例子)
放個(gè)圖片占位:
C++ STL主要組件之String總結(jié)(第二部分  深、淺拷貝問題以及賦值運(yùn)算符重載)
2.深拷貝
“如果一個(gè)類中涉及到資源的管理,其拷貝構(gòu)造函數(shù)、賦值運(yùn)算符重載以及析構(gòu)函數(shù)必須要顯式給出。一般情況都是按照深拷貝方式提供”
上面這句話是真理!
首先給出深拷貝一般在string'類中的實(shí)現(xiàn):

String(const String& s)
 : _str(new char[strlen(s._str)+1])   // 看見這一步開辟空間就知道是深拷貝了
 {
 strcpy(_str, s._str);
 }

再來說深拷貝的定義:
每個(gè)string都需要空間來存放字符串,而當(dāng)使用一個(gè)string類對象來構(gòu)造另一個(gè)string類對象。就用到了深拷貝:給每個(gè)對象獨(dú)立分配資源,保證多個(gè)對象之間不會(huì)因共享資源而造成空間多次釋放而造成的程序奔潰問題。

三.String中賦值運(yùn)算符重載
1.先給出幾種在string中常用的賦值運(yùn)算符重載:
<1> <<

ostream& bit::operator<<(ostream& _cout, const self::String& s)
{
 cout << s._str;
 return _cout;
}

對于<<的重載算是比較特殊的了,因?yàn)闀?huì)用到ostream類型,所以在這里展開說明一下:
ostream是output stream的簡稱,即輸出流。一個(gè)典型的輸出流對象就是在C++中標(biāo)準(zhǔn)輸出流cout。
在C++中,很少自定義ostream的對象,更多的是直接使用cout。
ostream這個(gè)類型,往往出現(xiàn)在<<操作重載中,作為某個(gè)類的友元函數(shù)出現(xiàn)。
比如對于class A, 可以定義ostream & operator << (ostream &os, const A& a);
這樣在調(diào)用A的對象var時(shí),就可以這樣使用
cout &lt;&lt; var ;

<2> =

String& operator=(String s)
 {
 swap(_str, s._str); 
 return *this;
 }

<3> +=

string& operator+=(char ch)
        {
            push_back(ch);
            return *this;
        }

<4> [ ]

char& operator[](size_t index)
 {
 assert(index < _size);
 return _str[index];
 }

四.最后是給出的較為完整的string類模擬實(shí)現(xiàn):

namespace key
{
 class String
 {
 public:
 typedef char* iterator;
 public:
 String(const char* str = "")
 {
 _size = strlen(str);
 _capacity = _size;
 _str = new char[_capacity+1];
 strcpy(_str, str);
 }
 String(const String& s)
 : _str(nullptr)
 , _size(0)
 , _capacity(0)
 {
 String tmp(s);
 this->Swap(tmp);
 }
 String& operator=(String s)
 {
 this->Swap(s)
 return *this;
 }
 ~String()
 {
 if (_str)
 {
 delete[] _str;
 _str = nullptr;
 }
 }
 /////////////////////////////////////////////////////////////////
 // iterator
 iterator begin() {return _str;}
 iterator end(){return _str + _size;}
 /////////////////////////////////////////////////////////////////
 // modify
 void PushBack(char c)
 {
 if (_size == _capacity)
 Reserve(_capacity*2);

 _str[_size++] = c;
 _str[_size] = '\0';
 }
 String& operator+=(char c)
 {
 PushBack(c);
 return *this;
 }
 void Clear()
 {
 _size = 0;
 _str[_size] = '\0';
 }
 void Swap(String& s)
 {
 swap(_str, s._str);
 swap(_size, s._size);
 swap(_capacity, s._capacity);
 }
 const char* C_Str()const
 {
 return _str;
 }
 size_t Size()const
 size_t Capacity()const
 bool Empty()const

 void Resize(size_t newSize, char c = '\0')
 {
 if (newSize > _size)
 {
 // 如果newSize大于底層空間大小,則需要重新開辟空間
 if (newSize > _capacity)
 {
 Reserve(newSize);
 }
 memset(_str + _size, c, newSize - _size);
 }
 _size = newSize;
 _str[newSize] = '\0';
 }
 void Reserve(size_t newCapacity)
 {
 // 如果新容量大于舊容量,則開辟空間
比特科技
 if (newCapacity > _capacity)
 {
 char* str = new char[newCapacity + 1];
 strcpy(str, _str);
 // 釋放原來舊空間,然后使用新空間
 delete[] _str;
 _str = str;
 _capacity = newCapacity;
 }
 }
 char& operator[](size_t index)
 {
 assert(index < _size);
 return _str[index];
 }
 const char& operator[](size_t index)const
 {
 assert(index < _size);
 return _str[index];
 }
 private:
 friend ostream& operator<<(ostream& _cout, const bit::String& s);
 private:
 char* _str;
 size_t _capacity;
 size_t _size;
 };
}
ostream& key::operator<<(ostream& _cout, const bit::String& s)
{
 cout << s._str;
 return _cout;
}

網(wǎng)站題目:C++STL主要組件之String總結(jié)(第二部分深、淺拷貝問題以及賦值運(yùn)算符重載)
URL標(biāo)題:http://muchs.cn/article40/pppheo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供面包屑導(dǎo)航、網(wǎng)站設(shè)計(jì)、定制開發(fā)、微信公眾號(hào)、網(wǎng)站排名軟件開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營