日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

浅谈深浅拷贝问题(这里只针对拷贝构造函数和赋值运算符重载)和简易srting类模拟实现

發(fā)布時間:2024/4/11 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浅谈深浅拷贝问题(这里只针对拷贝构造函数和赋值运算符重载)和简易srting类模拟实现 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

淺談深淺拷貝問題(這里只針對拷貝構(gòu)造函數(shù)和賦值運(yùn)算符重載)和簡易srting類模擬實(shí)現(xiàn)

文章目錄

    • 淺談深淺拷貝問題(這里只針對拷貝構(gòu)造函數(shù)和賦值運(yùn)算符重載)和簡易srting類模擬實(shí)現(xiàn)
    • 一、什么是淺拷貝
    • 二、再談淺拷貝
    • 三、淺拷貝的解決方法(只針對拷貝構(gòu)造函數(shù)和賦值運(yùn)算符重載)
      • 1.**深拷貝**:
      • 2.**`淺拷貝+引用計(jì)數(shù)`**:
    • 四、簡易模擬實(shí)現(xiàn)string類

一、什么是淺拷貝

淺拷貝也叫值拷貝、位拷貝,是編譯器將被拷貝的對象原封不動的拷貝過來(注意是原封不動的拷貝),也就是編譯器只把被拷貝的對象的值拷貝過來而已; 注意編譯器提供默認(rèn)淺拷貝的拷貝構(gòu)造函數(shù)不一定會造成操作違規(guī),但如果對象中涉及資源管理問題,就會導(dǎo)致其中一個對象使用完這份資源后,把這份資源給釋放了,然而其他共享這些資源的對象以為該資源還存在,當(dāng)對該資源進(jìn)行訪問操作時,就會導(dǎo)致訪問操作違規(guī)。

二、再談淺拷貝

假如模擬實(shí)現(xiàn)string類時,我們沒有顯式提供拷貝構(gòu)造函數(shù)和賦值運(yùn)算符重載,編譯器就會默認(rèn)生成一個拷貝構(gòu)造函數(shù)和一個賦值運(yùn)算符重載,但編譯器默認(rèn)生成的都是淺拷貝函數(shù);如:

在上圖中:

void Test() { string s1("hello world");//調(diào)用構(gòu)造函數(shù) string s2(s1);//此時調(diào)用拷貝構(gòu)造函數(shù) }
  • 代碼中我們沒有顯式定義拷貝構(gòu)造函數(shù),編譯器會默認(rèn)生成一個淺拷貝的拷貝構(gòu)造函數(shù),此時拷貝構(gòu)造函數(shù)會把s1原封不動的拷貝過去,
  • 但s1._pstr此時是指向"hello world"字符串,然后s2._pstr把s1._pstr拷貝過去,使得s2._pstr得到字符串的首地址,后s2._pstr也就指向"hello world"字符串,使得s1、s2共享一份空間的資源;
  • 當(dāng)完成s2的拷貝構(gòu)造后,出Test函數(shù)時,首先調(diào)用s2的析構(gòu)函數(shù)銷毀s2對象,s2為了防止內(nèi)存泄漏,就會把其使用后的資源回收,
  • 當(dāng)釋放s1時,s1._pstr雖然仍指向那個空間,此時那片空間已被s2的析構(gòu)函數(shù)回收,s1._pstr已沒有那片空間的使用權(quán),造成s1._pstr是一個野指針,
  • 但s1不知到該資源已經(jīng)被s2釋放,然后s1繼續(xù)釋放該空間資源,造成一份資源多次釋放,且s1想調(diào)用析構(gòu)函數(shù)回收s1._pstr指向的那份空間時,因?yàn)閟1._pstr已沒有那片空間的使用權(quán),兩者都會引起程序崩潰。
  • 三、淺拷貝的解決方法(只針對拷貝構(gòu)造函數(shù)和賦值運(yùn)算符重載)

    1.深拷貝

    從上面可以知道產(chǎn)生淺拷貝的原因主要有一份資源被多次釋放和想銷毀一個野指針指向的空間,那么深拷貝就從根源上解決問題:
    此時對于拷貝構(gòu)造函數(shù):

    string(const string&s) :_str(new char[strlen(s._str]+1) {strcpy(_str,s._str); }

    對于賦值運(yùn)算重載:

    string& operator=(const string& s) {if(this!=&s){char*_pstr=new char[strlen(s._str)+1];//防止第二個字符串太長,所以另外申請空間strcpy(_pstr,s._str);delete[] _str;_str=_pstr;}return *this; }

    通過上面的代碼,就解決了引起淺拷貝的兩個問題,主要解決思想是另外申請一個空間,把內(nèi)容拷貝過去,這樣就不會存在資源共享問題,也就不存在淺拷貝,但上面代碼利用率低,復(fù)用性不高。

    當(dāng)然深拷貝也可以這樣解決,代碼如下:

    對于拷貝構(gòu)造函數(shù):

    string(const string& s) :_str(nullptr) {string strTemp(s._str);swap(_str,strTemp._str); }
  • 上面的代碼中對_str(nullptr)的初始化是必須的,因?yàn)闃?gòu)造函數(shù)肯定是不會出現(xiàn)淺拷貝問題的,
  • 所以首先調(diào)用構(gòu)造函數(shù)構(gòu)造一個臨時對象strTemp,把s的內(nèi)容進(jìn)行一份拷貝,
  • 然后用swap函數(shù)把_str和strTemp._str這兩個指針進(jìn)行交換,這樣_str就得到s的那份拷貝,而strTemp._str就得到nullptr,當(dāng)出拷貝構(gòu)造函數(shù)是,釋放臨時對象strTemp,因?yàn)榇藭rstrTemp._str已經(jīng)為空,析構(gòu)函數(shù)就不會對其空間進(jìn)行釋放,
  • 所以_str(nullptr)的初始化是必須的,這樣就解決了拷貝構(gòu)造函數(shù)的淺拷貝問題。
    對于賦值運(yùn)算符重載:
  • string& operator=(string s) {swap(_str,s._str);return *this; } /* string& operator=(string& s) {if(this!=&s){string strTemp(s._str);swap(_str,strTemp._str);}return *this; } */
  • 對于上面的代碼,第一種方法傳遞的參數(shù)為string s,相當(dāng)于是s的一份臨時拷貝,此時s的改變不會引起實(shí)參的改變,然后把_str和s._str進(jìn)行交換,然后返回this,出作用域后,臨時對象就被銷毀,不用顯示銷毀。
  • 對于第二種方法:首先進(jìn)行判斷,避免了自己給自己賦值,和拷貝構(gòu)造函數(shù)思想基本一樣,賦值運(yùn)算符重載首先通過構(gòu)造函數(shù)構(gòu)造一個臨時變量strTemp,這樣strTemp就得到s._str的一份拷貝,然后把_str和strTemp._str進(jìn)行交換,這樣_str就得到s._str的一份拷貝,strTemp._str得到_str的內(nèi)容,最后釋放strTemp臨時對象時,strTemp._str得到_str的內(nèi)容也就被析構(gòu)函數(shù)回收釋放了,不會造成資源泄漏。
  • 2.淺拷貝+引用計(jì)數(shù):

    (1).通過這種方法解決主要思想是:

    a.怎么解決多次釋放一份資源問題:此時是和教室里最后一個人走關(guān)燈一樣,如果我們知道當(dāng)前共有多少個對象共享一份資源,當(dāng)一個對象準(zhǔn)備釋放時,如果發(fā)現(xiàn)還有對象使用這份資源,就不釋放,此時就解決一份資源多次釋放問題

    b.怎么知道當(dāng)前共有多少個對象共享這份資源:引用計(jì)數(shù)

    (2)拷貝構(gòu)造函數(shù)的解決方法:

    (注意之所以把錯解寫出來,是因?yàn)楹竺婷恳徊蕉际窃阱e解的基礎(chǔ)上進(jìn)行改正的,方便理解)

    錯解1:在成員中定義一個int型變量,用來記錄共享這份資源的對象的個數(shù)

    #if 0 namespace wolf {class string{public:string(const char* str = "")//構(gòu)造函數(shù):_str(new char[strlen(str) + 1]){if (str == nullptr){str = "";}_count = 1;//因?yàn)橐坏┩ㄟ^構(gòu)造函數(shù)來構(gòu)造一個對象,說明這個對象的//資源只有它自己用,還沒來得及共享,就把_count置為1strcpy(_str, str);}string(string& s)//拷貝構(gòu)造函數(shù):_str(s._str)//在拷貝構(gòu)造函數(shù)中采用淺拷貝的方式,_count(++s._count)//string s1("wolf");string s2(s1);此時對//象s2通過拷貝構(gòu)造函數(shù)共享s1這個對象的資源時,//就把s1._count加1,表明現(xiàn)在除了s1自己外還有別人共享這份資源,然后把//s1._count賦值給需要共享的對象s2,//此時s2._count也記錄了當(dāng)前共享一份資源的對象的個數(shù);{}string& operator=(const string& s)//賦值運(yùn)算符重載{if (this != &s)//防止自己給自己賦值{//.....}return *this;}~string()//析構(gòu)函數(shù){if (_str&&(--_count==0))//_count-1==0的意思是除去自己這個對象使//用這份資源外,如果為0,表明除了自己//沒有其他對象共享這份資源,此時釋放就不會引起一份資源被多次釋放的//問題,反之_count-1!=0就表示//還有對象使用這份資源,此時就不能釋放。{delete[] _str;_str = nullptr;}}private:char* _str;int _count;}; } #endif

    string s1(“wolf”);string s2(s1);通過調(diào)試發(fā)現(xiàn)這種放法是錯誤的,因?yàn)楫?dāng)s2釋放后,s2._count確實(shí)減少了,但是當(dāng)我們?nèi)メ尫舠1時,s1的s2._count仍為2,這樣s2就沒有釋放,最終導(dǎo)致資源泄露

    錯解2:因?yàn)榈谝环N方法放法主要是_count不同步造成的,所以采用static修飾_count的方法

    #if 0 namespace wolf {class string{public:string(const char* str = "")//構(gòu)造函數(shù):_str(new char[strlen(str) + 1]){if (str == nullptr){str = "";}_count = 1;//因?yàn)橐坏┩ㄟ^構(gòu)造函數(shù)來構(gòu)造一個對象,說明這個對象的資源只//有它自己用,還沒來得及共享,所以就把_count置為1strcpy(_str, str);}string(string& s)//拷貝構(gòu)造函數(shù):_str(s._str)//在拷貝構(gòu)造函數(shù)中采用淺拷貝的方式{_count++;//}string& operator=(const string& s)//賦值運(yùn)算符重載{if (this != &s)//防止自己給自己賦值{//.......}return *this;}~string()//析構(gòu)函數(shù){if (_str && (--_count == 0))//_count-1==0的意思是除去自己這個對//象使用這份資源外,如果為0,表明除了自己//沒有其他對象共享這份資源,此時釋放就不會引起一份資源被多次釋放的//問題,反之_count-1!=0就表示//還有對象使用這份資源,此時就不能釋放。{delete[] _str;_str = nullptr;}}private:char* _str;static int _count;};int string::_count = 0; } #endif
  • 這種方法有一個嚴(yán)重的問題:就是因?yàn)開count時靜態(tài)的,是所有對象共享的,當(dāng)執(zhí)行string s1("wolfguidao");string s2(s1);是完全沒有問題的,
  • 但一旦執(zhí)行string s3;因?yàn)閟3是另外通過構(gòu)造函數(shù)創(chuàng)建的對象,使用的是另外一份資源,沒有和s1s2共享,此時_count應(yīng)該=1;這樣就會影響到s1s2的釋放問題,計(jì)數(shù)因該和資源個數(shù)保持一致。
  • 正解:如果每一份資源都有自己的一個計(jì)數(shù),這樣計(jì)數(shù)就和資源個數(shù)保持一致,所以采用共享計(jì)數(shù)的方法

    namespace wolf {class string{public:string(const char* str = "")//構(gòu)造函數(shù):_str(new char[strlen(str) + 1]),_pcount(new int (1))//在堆上申請一個空間并初始化為1;{if (str == nullptr){str = "";}strcpy(_str, str);}string(string& s)//拷貝構(gòu)造函數(shù):_str(s._str)//在拷貝構(gòu)造函數(shù)中采用淺拷貝的方式,_pcount(s._pcount)//共享同一份資源的計(jì)數(shù){++(*_pcount);}string& operator=(const string& s)//賦值運(yùn)算符重載{if (this != &s)//防止自己給自己賦值{//.........}return *this;}~string()//析構(gòu)函數(shù){if (_str && (--(*_pcount) == 0))//_pcount-1==0的意思是除去自己//這個對象使用這份資源外,如果為0,表明除了自己//沒有其他對象共享這份資源,此時釋放就不會引起一份資源被多次釋放的//問題,反之_pcount-1!=0就表示//還有對象使用這份資源,此時就不能釋放。{delete[] _str;_str = nullptr;delete _pcount;_pcount = nullptr;}}private:char* _str;int* _pcount;}; } #endif
  • 執(zhí)行string s1("wolf guidao");string s2(s1);通過這種方法每份資源都有自己的計(jì)數(shù)空間,如果有其他對象s2共享這份 資源s1,
  • 同時也就共享了這份資源的計(jì)數(shù);string s3;s3是另外一份資源,s3的資源內(nèi)容和計(jì)數(shù)空間都是另外一份,就不會共享s1的內(nèi)容和s1的資源計(jì)數(shù),這種方法就解決了上面一種法方法的問題。
  • (3).賦值運(yùn)算符重載的解決方法
    經(jīng)過上面的鋪墊就很容易的到賦值運(yùn)算符重載的解決方法:

    namespace wolf {class string{public:string(const char* str = "")//構(gòu)造函數(shù):_str(new char[strlen(str) + 1]), _pcount(new int(1))//在堆上申請一個空間并初始化為1;{if (str == nullptr){str = "";}strcpy(_str, str);}string(string& s)//拷貝構(gòu)造函數(shù):_str(s._str)//在拷貝構(gòu)造函數(shù)中采用淺拷貝的方式, _pcount(s._pcount)//共享同一份資源的計(jì)數(shù){++(*_pcount);}//1.s3 = s2;如果賦值成功,s2,s3就會共享同一份資源,s2那份資源就多一個共//享對象,所以共享s2那份資源的計(jì)數(shù)加1//2.s3原來的那份資源就不會再使用,所以要釋放s3,那么共享s3這份資源的對象就//少一份,所以就因該把共享s3的計(jì)數(shù)減1//如果把s3的計(jì)數(shù)減1后剛好為0,表示只有s3使用者一份資源,那么為了防止資源泄//露,需要手動釋放string& operator=(const string& s)//賦值運(yùn)算符重載{//此時_pcount為s3,s._pcount為s2if (this != &s)//防止自己給自己賦值{if (--(*_pcount) == 0){delete[] _str;delete _pcount;}_str = s._str;_pcount = s._pcount;++(*_pcount);}return *this;}~string()//析構(gòu)函數(shù){if (_str && (--(*_pcount) == 0))//_pcount-1==0的意思是除去自己//這個對象使用這份資源外,如果為0,表明除了自己//沒有其他對象共享這份資源,此時釋放就不會引起一份資源被多次釋放的//問題,反之_pcount-1!=0就表示//還有對象使用這份資源,此時就不能釋放。{delete[] _str;_str = nullptr;delete _pcount;_pcount = nullptr;}}private:char* _str;int* _pcount;}; } #endif

    以上解決淺拷貝的方法也有其問題:如果修改對象s3中的資源時s3[0] = ‘W’;,就發(fā)現(xiàn)其他和其共享資源的對象s1,s2也發(fā)生了改變,相當(dāng)于一改全改接下來就是想怎么解決這一問題。

    (4).解決淺拷貝+引用計(jì)數(shù)的缺陷:寫時拷貝copy on write(COW)(這里只針對部分)

  • string s1(“wolf guidao”);string s2(s1);string s3;s3 =s2;前面的代碼都是沒有問題的,
  • 但是s3[0] = ‘W’;就會出現(xiàn)問題,如果想解決這個問題;就因該進(jìn)行判斷,如果有其他對象s1,s2共享這份資源,就應(yīng)該另外申請空間把s3對象分離出來,且把共享的這份資源拷貝一份,避免一改全改的問題,這就是寫時拷貝。
  • 如果沒有其他對象和s3共享同一份資源,就不用分離。
  • 分離對象的時機(jī):所有的寫操作||或可能會引起寫操作都應(yīng)分離
  • namespace wolf {class string{public:string(const char* str = "")//構(gòu)造函數(shù):_str(new char[strlen(str) + 1]), _pcount(new int(1))//在堆上申請一個空間并初始化為1;{if (str == nullptr){str = "";}strcpy(_str, str);}string(string& s)//拷貝構(gòu)造函數(shù):_str(s._str)//在拷貝構(gòu)造函數(shù)中采用淺拷貝的方式, _pcount(s._pcount)//共享同一份資源的計(jì)數(shù){++(*_pcount);}//1.s3 = s2;如果賦值成功,s2,s3就會共享同一份資源,s2那份資源就多一個共//享對象,所以共享s2那份資源的計(jì)數(shù)加1//2.s3原來的那份資源就不會再使用,所以要釋放s3,那么共享s3這份資源的對象就//少一份,所以就因該把共享s3的計(jì)數(shù)減1//如果把s3的計(jì)數(shù)減1后剛好為0,表示只有s3使用者一份資源,那么為了防止資源泄//露,需要手動釋放string& operator=(const string& s)//賦值運(yùn)算符重載{//此時_pcount為s3,s._pcount為s2if (this != &s)//防止自己給自己賦值{if (--(*_pcount) == 0){delete[] _str;delete _pcount;}_str = s._str;_pcount = s._pcount;++(*_pcount);}return *this;}~string()//析構(gòu)函數(shù){if (_str && (--(*_pcount) == 0))//_pcount-1==0的意思是除去自己//這個對象使用這份資源外,如果為0,表明除了自己//沒有其他對象共享這份資源,此時釋放就不會引起一份資源被多次釋放的//問題,反之_pcount-1!=0就表示//還有對象使用這份資源,此時就不能釋放。{delete[] _str;_str = nullptr;delete _pcount;_pcount = nullptr;}}char& operator[](size_t index)//下標(biāo)運(yùn)算符重載{//該操作可能會改變當(dāng)前對象的內(nèi)容,從而引起其他共享對象內(nèi)容的改變,所以//因該采用分離當(dāng)前對象操作if (Getpcount() > 1)//滿足條件就表示有其他對象共享資源,就因該分離{string strtemp(_str);this->Swap(strtemp);}return _str[index];}//執(zhí)行s3[0] = 'W'時,因?yàn)閟1,s2和其共享一份資源,臨時對象strtemp._str//指向原本s3共享的那份_str,//strtemp._pcount指向_pcount,當(dāng)出該函數(shù)時,根據(jù)_pcount的值看是否要釋//放資源。//最后當(dāng)釋放對象s3時,因?yàn)閟trtemp是通過構(gòu)造函數(shù)string strtemp(_str);來//創(chuàng)建的,所以strtrmp._pcount=1,經(jīng)過//交換后s3._pcount=1;所以s3可以正常釋放。void Swap(string& s)//交換兩個對象{swap(_str, s._str);//交換字符串內(nèi)容swap(_pcount, s._pcount);//交換資源計(jì)數(shù)}private:int Getpcount(){return *_pcount;}char* _str;int* _pcount;}; }

    main函數(shù):

    void TestMystring() {wolf::string s1("wolf guidao");wolf::string s2(s1);wolf::string s3;s3 = s2;s3[0] = 'W'; }int main() {TestMystring();system("pause");return 0; }

    以上代碼中每一步都有詳細(xì)解釋,如果還不明白,下面鏈接中有介紹淺拷貝+引用計(jì)數(shù)的使用方法和這種方法的缺點(diǎn);
    淺拷貝+引用計(jì)數(shù)解決淺拷貝
    淺拷貝+引用計(jì)數(shù)解決淺拷貝問題的缺陷

    四、簡易模擬實(shí)現(xiàn)string類

    #define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<Windows.h> #include<stdlib.h> #include<string.h> using namespace std;namespace wolf {class string{public:typedef char* iterator;public:string(const char* str = "")//構(gòu)造函數(shù){if (str == nullptr)//如果傳進(jìn)來為空指針,就讓他改為"",這樣就可以放止程序崩潰{str = "";}_size = strlen(str);_capacity = _size;_str = new char[_capacity+1];//申請空間strcpy(_str, str);//把str中的內(nèi)容拷貝過去}string(const string& s)//拷貝構(gòu)造函數(shù);采用深拷貝:_size(s._size),_capacity(s._size+1){_str = new char[_capacity];strcpy(_str, s._str);}string& operator=(string& s)//賦值運(yùn)算符重載{if (this != &s){string temp(s._str);//調(diào)用構(gòu)造函數(shù)把s的字符串拷貝一份,防止淺拷貝問題swap(_str, temp._str);}return *this;}~string()//析構(gòu)函數(shù){if (_str)//不為空才進(jìn)行釋放,否則會多次釋放{_size = 0;_capacity = 0;delete[] _str;_str = nullptr;}}size_t Size()const//返回字符串個數(shù){return _size;}size_t Capacity()const//返回空間容量daxiao{return _capacity;}bool Empty()const//判空{return _size == 0;}iterator begin()//迭代器(注意迭代器的范圍都是[begin,end)){return _str;//返回字符串首地址}iterator end(){return _str + _size;//返回字符串最后一個位置,即\0出}void Reserve(size_t newcapacity)//調(diào)整空間大小{if (newcapacity > _capacity)//如果新空間大小大于舊空間大小才進(jìn)行{char* strtemp = new char[newcapacity + 1];//多一個是為了放'\0'strcpy(strtemp, _str);delete[]_str;_str = strtemp;_capacity = newcapacity;//新空間大小不是newcapacity+1是為了和類庫中string保持一致}}void Resize(size_t newsize,char ch)//把空間中有效字符個數(shù)調(diào)整為newsize的,多余的空間用ch填充{size_t oldsize = Size();if (newsize < oldsize)//如果調(diào)整后有效字符個數(shù)小于原有字符個數(shù){_size = newsize;_str[_size] = '\0';}else{if (newsize > _capacity)//如果調(diào)整后字符個數(shù)大于空間容量,就進(jìn)行擴(kuò)容{Reserve(newsize);}memset(_str+_size, ch, newsize - oldsize);//從原有字符后面進(jìn)行填充ch}_size = newsize;_str[_size] = '\0';//記得加上\0}void Push_back(char ch)//在原來字符串末尾追加一個字符ch{if (_size == _capacity)//判滿{Reserve(_capacity * 2);}_str[_size++] = ch;_str[_size] = '\0';}string& operator+=(char ch)//運(yùn)算符重載{if (_size == _capacity){Reserve(_capacity * 2);}Push_back(ch);_size = _size + 1;return *this;}void Append(const char* str);//追加字符串string& operator+=(const char* str);//運(yùn)算符重載void Clear()//把空間中有效字符個數(shù)清空{_size = 0;_str[_size] = '\0';}void Swap(string& s)//把兩個string對象中的內(nèi)容交換,注意要全部交換{swap(_str, s._str);swap(_size, s._size);swap(_capacity, s._capacity);}const char* C_str()const//返回當(dāng)前對象的C格式字符串{return _str;}char& operator[](size_t index)//運(yùn)算符重載{if (index < _size){return _str[index];}}bool operator>(const string& s)const;bool operator>=(const string& s)const;bool operator<(const string& s)const;bool operator<=(const string& s)const;bool operator==(const string& s)const;bool operator!=(const string& s)const;int Find(char ch, size_t pos = 0)const//從pos開始,從前往后找字符,返回ch的下標(biāo){for (size_t i = pos;i < _size;i++){if (_str[i] == ch){return i;}}return -1;}int rFind(char ch, size_t pos = -1)const//從pos開始,從后往前找字符,返回ch的下標(biāo){if (pos == npos){pos = _size - 1;}for (size_t i = pos;i >= 0;i--){if (_str[i] == ch){return i;}}return npos;}int Find(char* str, size_t pos = 0)const//從pos開始,從前往后找字符串,返回str的下標(biāo){}int rFind(char* str, size_t pos = 0)const//從pos開始,從后往前找字符串,返回str的下標(biāo){}string& Erase(size_t pos,size_t num)//從pos開始刪除num個字符{}string& Insert(size_t pos,char ch)//在pos處插字符ch{}string& Insert(size_t pos, char* str)//在pos處插字符串str{}friend ostream& operator<<(ostream& _cout, const string& s){_cout << s.C_str();return _cout;}friend istream& operator>>(istream& _cin, const string& s){_cin >> s._str;return _cin;}private:char* _str;//存放字符串size_t _size;//字符串個數(shù)size_t _capacity;//字符串容量static size_t npos;}; }size_t wolf::string::npos = -1;void Teststeing() {wolf::string a("wolf");//cout << a.Size() << endl;//cout << a.Capacity() << endl;wolf::string b(a);//cout << b.Size() << endl;//cout << a.Capacity() << endl;b.Resize(10, '!');//cout << b << endl;//cout << b.Size() << endl;//cout << b.Capacity() << endl;b.Reserve(30);//cout << b.Capacity() << endl;b.Push_back(' ');b.Push_back('i');//cout << b << endl;//b.Clear();//cout << b << endl;//cout << b.Find('o') << endl;//cout << b.rFind('o') << endl;//cout << b.C_str() << endl;wolf::string::iterator it = b.begin();/*while (it < b.end()){cout << *it;it++;}*///cout << endl;/*for (auto e: b){cout << e;}*///cout << endl;wolf::string c;cin >> c;cout << c; }int main() {Teststeing();system("pause");return 0; }

    總結(jié)

    以上是生活随笔為你收集整理的浅谈深浅拷贝问题(这里只针对拷贝构造函数和赋值运算符重载)和简易srting类模拟实现的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。