C++的深淺拷貝和寫(xiě)時(shí)拷貝你了解嗎
1.淺拷貝
淺拷貝:對(duì)于有申請(qǐng)空間的對(duì)象的類(lèi)來(lái)說(shuō),是按照字節(jié)序依次拷貝過(guò)去的,并沒(méi)有另外申請(qǐng)一塊空間。因此,在調(diào)用析構(gòu)函數(shù)的時(shí)候會(huì)造成同一塊空間釋放兩次的情況,從而使程序崩潰。
如下實(shí)例:
class string { public: string(const char* str) { //構(gòu)造string類(lèi)對(duì)象時(shí),如果傳遞nullptr指針 //認(rèn)為程序非法,此處斷言下 assert(str); _str = new char[strlen(str) + 1]; strcpy(_str, str); } ~string() { if (_str) { delete[] _str; _str = nullptr; } } private: char* _str; }; void test() { string s1("linmanman"); string s2(s1); }
運(yùn)行看看,報(bào)錯(cuò)了
分析錯(cuò)因:
淺拷貝是指向同一塊空間的,這樣就會(huì)有倆個(gè)無(wú)法避免的問(wèn)題:
1.析構(gòu)倆次空間,程序崩潰
2.其中一個(gè)的值被修改了,會(huì)影響到另外一個(gè)的值。
深拷貝:給每個(gè)對(duì)象單獨(dú)分配資源,就是給待拷貝的對(duì)象另開(kāi)一片空間,再把原對(duì)象空間上的值拷貝過(guò)來(lái),這樣在調(diào)用析構(gòu)函數(shù)的時(shí)候就不會(huì)產(chǎn)生沖突。
2.深拷貝
傳統(tǒng)寫(xiě)法的string類(lèi)的深拷貝是自己開(kāi)空間,自己將拷貝的對(duì)象拷貝到待拷貝對(duì)象中。
string(const string& s) : _str(new char[strlen(s._str)+1]) { strcpy(_str, s._str); } 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; }
現(xiàn)代寫(xiě)法的string類(lèi)的深拷貝堪稱(chēng)是“移花接木”
string(const string& s) :_str(nullptr)//必須置空,因?yàn)開(kāi)str開(kāi)始是個(gè)隨機(jī)數(shù),交換給tmp._str后,釋放會(huì)引起問(wèn)題 { string tmp(s._str);//直接利用構(gòu)造函數(shù),給tmp對(duì)象開(kāi)辟了一塊空間 swap(tmp); } string& operator=(string s) { swap(s);//這個(gè)swap是咱們自己寫(xiě)的哦 return *this; }
順帶提一嘴,各個(gè)編譯器深拷貝的底層實(shí)現(xiàn)略有差異(當(dāng)然邏輯是一樣的)
VS 2013下的深拷貝
g++下的深拷貝
3.引用計(jì)數(shù)+寫(xiě)時(shí)拷貝
寫(xiě)時(shí)拷貝就是一種拖延癥, 是在淺拷貝的基礎(chǔ)之上增加了引用計(jì)數(shù)的方式來(lái)實(shí)現(xiàn)的。
引用計(jì)數(shù):用來(lái)記錄資源使用者的個(gè)數(shù)。在構(gòu)造時(shí),將資源的計(jì)數(shù)給成1,每增加一個(gè)對(duì)象使用該資源,就給計(jì)數(shù)增加1,當(dāng)某個(gè)對(duì)象被銷(xiāo)毀時(shí),先給該計(jì)數(shù)減1,然后再檢查是否需要釋放資源,如果計(jì)數(shù)為1,說(shuō)明該對(duì)象時(shí)資源的最后一個(gè)使用者, 將該資源釋放;否則就不能釋放,因?yàn)檫€有其他對(duì)象在使用該資源。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
c++ dynamic_cast與static_cast使用方法示例
本文用示例講解了dynamic_cast、static_cast子類(lèi)與基類(lèi)之間轉(zhuǎn)換功能的使用方法2013-11-11C++中基類(lèi)和派生類(lèi)之間的轉(zhuǎn)換實(shí)例教程
這篇文章主要介紹了C++中基類(lèi)和派生類(lèi)之間的轉(zhuǎn)換,有助于深入理解C++面向?qū)ο蟪绦蛟O(shè)計(jì),需要的朋友可以參考下2014-08-08C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)二叉樹(shù)先序、中序、后序及層次四種遍歷
這篇文章主要介紹了C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)二叉樹(shù)先序、中序、后序及層次四種遍歷方式,具有一定的知識(shí)性參考價(jià)值,需要的小伙伴可以先看一下2022-02-02