Effective C++学习第四天
條款11:在operator=中處理自我賦值的現(xiàn)象
? ? ? ? ? ?雖然我們在平時(shí)可能不會出現(xiàn)顯示自我賦值的現(xiàn)象,當(dāng)加入指針或者引用時(shí),可能會出現(xiàn)不同的指針或引用指向同一對象(對象的不同別名),這時(shí)候我們就得考慮對象是否是同一個(gè);考慮到要保證系統(tǒng)的自我賦值安全性和異常安全性的角度,可以采用的方案是:將原來的被賦值對象做一個(gè)副本,然后讓被賦值對象指向復(fù)制對象,最后刪除副本即可,代碼如下:
? ? ? ? widget& widget::operator=(const widget & rhs){
? ? ? ? ? ? ? ? ? ? bitmap *porig=pb;? ? ? ? ? ? ? ? ? ? ? ? ? //pb為類widget的一個(gè)類型為bitmap的指針
? ? ? ? ? ? ? ? ? ? pb=new? bitmap(*rhs.pb);
? ? ? ? ? ? ? ? ? ? delete porig;
? ? ? ? ? ? ? ? ? ? return *this;
? ? ? ? ? }
? ? ? ? ? ?最好的方法是采用copy and swap的方案,代碼如下:(方案1采用傳引用的方法,方案2采用傳值的方法
? ? ? ?void swap(widget &rhs)? {....};? ? //交換rhs和*this的數(shù)據(jù);
? ? 方案1: widget &widget::operator=(const widget & rhs){? ? ? ? ? ? ? 方案2: widget&widget::operator=(widget rhs)
? ? ? ? ? ? ? ? ? ? widget temp(rhs);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? {? ?
? ? ? ? ? ? ? ? ? ? swap(temp);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?swap(rhs);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? ? ? ?return *this;? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? return *this;
? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
條款12:復(fù)制對象時(shí)勿忘其每個(gè)成分
? ? ? ? ? 當(dāng)自己定義copy函數(shù)時(shí)(copy構(gòu)造和copy assignment),編譯器不再給我們提供新的copy函數(shù),因此在拷貝的過程中,我們要確定所有的成員變量都被拷貝;
? ? ? ? ? 當(dāng)我們?yōu)閏lass增添新的成員變量時(shí),我們需要修改我們所有的copy函數(shù),構(gòu)造函數(shù),采用繼承的方式可以避免代碼的過多修改,但是你必須保證base class的成員變量也被初始化,也就是在derived class的拷貝函數(shù)初始化列表或者函數(shù)體中調(diào)用base class的拷貝函數(shù);如果不這樣做,derived class在構(gòu)造copy函數(shù)的時(shí)候會調(diào)用base class的default copy函數(shù),但是base class的copy函數(shù)是被阻止的,因此此時(shí)編譯器會報(bào)錯;
? ? ? ? ?結(jié)論:當(dāng)我們寫一個(gè)自定義的copy函數(shù)的時(shí)候,確定幾點(diǎn):1)復(fù)制所有的local成員變量;2)調(diào)用所有base class內(nèi)適當(dāng)?shù)腸opy函數(shù);
? ? ? ? ? ? 不要令copy assignment去調(diào)用copy構(gòu)造函數(shù);也不要讓copy構(gòu)造函數(shù)去調(diào)用copy assignment;
? ? ? ? ? ?當(dāng)copy assignment和copy 構(gòu)造函數(shù)有相近的代碼時(shí),可以把相同的代碼變成新的成員函數(shù),這樣的函數(shù)通常為private且常命名為init;
條款13:以對象管理資源
? ? ? ? ? ? ?以singleton(單例模式)的factory function為例,函數(shù)返回的是一個(gè)heap-base的指針,用戶在使用完這個(gè)對象之后需要把這個(gè)指針刪除,如何保證這個(gè)指針?biāo)赶虻馁Y源被刪除呢?可選用的方法是把:把資源放進(jìn)對象中,利用C++的“析構(gòu)函數(shù)自動調(diào)用機(jī)制”保證資源被釋放;
? ? ? ? ? ? ?C++標(biāo)準(zhǔn)程序庫中提供auto_ptr(類指針對象,也稱為智能指針),其析構(gòu)函數(shù)自動對其所指對象調(diào)用delete,常見的智能指針有unique_ptr,shared_ptr;weak_ptr;
? ? ? ? ? ? 以對象管理資源的兩個(gè)關(guān)鍵想法:1)獲得資源后立刻放進(jìn)管理對象內(nèi),實(shí)際上“以對象管理資源”的觀念通常被稱為“資源取得時(shí)機(jī)便是初始化時(shí)間(resource acquisition isinitialization RAII)”;2)管理對象運(yùn)用析構(gòu)函數(shù)確保資源被釋放(在析構(gòu)函數(shù)釋放資源時(shí),可能會出現(xiàn)異常,正確處理析構(gòu)函數(shù)中拋出異常的情況);
? ? ? ? ? ? auto_ptr的特性是被銷毀(調(diào)用copy函數(shù)時(shí)會發(fā)生)時(shí)自動刪除它的所指之物,并將自己的指針指向nullptr,因此不要讓對個(gè)auto_ptr指向同一個(gè)對象,如果這樣可能會出現(xiàn)對象被刪除一次以上;auto_ptr的性質(zhì)是始終只有一個(gè)指針取得資源的唯一擁有權(quán);
? ? ? ? ? auto_ptr的替代方案是:引用型計(jì)數(shù)指針(reference-counting smart pointer,RCSP),該指針特性就是持續(xù)追蹤多個(gè)指針指向同一資源,并在無人指向該資源時(shí)釋放資源,但是RCSP無法打破環(huán)形引用(也就是類中互相指向的問題,可用weak_ptr來解決這一現(xiàn)象);
? ? ? ? ?由于以對象管理資源在析構(gòu)函數(shù)中執(zhí)行的是delete而非delete[],因此動態(tài)分配的數(shù)組無法通過這種方式來實(shí)現(xiàn)內(nèi)存釋放,只能通過自己手工釋放內(nèi)存資源;
總結(jié)
以上是生活随笔為你收集整理的Effective C++学习第四天的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 有任务助手蓝总每日刷几盘能过
- 下一篇: Effective C++学习第五天