class Inverstment { ... };
Inverstment* createInverstment();
void f() {
Inverstment* pInv = createInverstment();
...
delete pInv;
}
某些特殊情況,例如 ... 這個區(qū)域存在return語句,delete語句不會被執(zhí)行到,造成內(nèi)存泄漏。使用std::shared_ptr解決此問題。
創(chuàng)新互聯(lián)公司致力于互聯(lián)網(wǎng)品牌建設與網(wǎng)絡營銷,包括成都網(wǎng)站設計、成都網(wǎng)站建設、外貿(mào)網(wǎng)站建設、SEO優(yōu)化、網(wǎng)絡推廣、整站優(yōu)化營銷策劃推廣、電子商務、移動互聯(lián)網(wǎng)營銷等。創(chuàng)新互聯(lián)公司為不同類型的客戶提供良好的互聯(lián)網(wǎng)應用定制及解決方案,創(chuàng)新互聯(lián)公司核心團隊十載專注互聯(lián)網(wǎng)開發(fā),積累了豐富的網(wǎng)站經(jīng)驗,為廣大企業(yè)客戶提供一站式企業(yè)網(wǎng)站建設服務,在網(wǎng)站建設行業(yè)內(nèi)樹立了良好口碑。void f() {
std::shared_ptrpInv1(createInverstment());
std::shared_ptrpInv2(pInv1);
pInv1 = pInv2;
...
}
shared_ptr在其析構(gòu)函數(shù)內(nèi)做delete而不是delete[]動作,對于array來說使用shared_ptr是個餿主意。
//餿主意,會用上錯誤的delete形式
std::shared_ptraps(new std::string[10]);
std::shared_ptrspi(new int[1024]);
請注意:
獲得資源后立刻放進管理對象;
管理對象運用析構(gòu)函數(shù)確保資源被釋放;
為了防止資源泄露,請使用RAII對象,它們在構(gòu)造函數(shù)中獲得資源并在析構(gòu)函數(shù)中釋放資源;
使用shred_ptr一般是較佳選擇。
條款14:在資源管理類中小心copying行為假如我們使用C API函數(shù)處理類型為Mutex的互斥鎖對象,有l(wèi)ock和unlock函數(shù)可用:
void lock(Mutex* pm);
void unlock(Mutex *pm);
創(chuàng)建一個class用來管理鎖
class Lock {
public:
? ? explicit Lock(Mutex *pm) : mutexPtr(pm) {
? ? ? ? lock(mutexPtr);
? ? }
? ??
? ? ~Lock() {
? ? ? ? unlock(mutexPtr);
? ? }
private:
? ? Mutex *mutexPtr;
};
客戶調(diào)用
Mutex m;
...
{
????Lock m1(&m);
}
這很好,但如果Lock對象被復制,會發(fā)生什么?
Lock ml1(&m);
Lock ml2(ml1);
大多數(shù)情況,會選擇以下兩種可能:
class Uncopyable {
protected:
Uncopyable() {}
~Uncopyable() {}
private:
Uncopyable(const Uncopyable &);
Uncopyable& operator=(const Uncopyable &);
};
class Lock : private Uncopyable {
public:
...
};
class Lock {
public:
? ? explicit Lock(Mutex *pm) : mutexPtr(pm, unlock) {
? ? ? ? lock(mutexPtr.get());
? ? }
private:
? ? std::shared_ptrmutexPtr;
};
請記?。?/p>
復制RAII對象必須一并復制它所管理的資源;
普遍而常見的RAII classcopying行為是:抑制copying、實施引用計數(shù)法。
條款15:在資源管理類中提供對原始資源的訪問std::shared_ptrpInv(createInverstment());
int daysHeld(const Inverstment* pi);
int days = daysHeld(pInv); //無法通過編譯
daysHeld需要時Inverstment*指針,傳給它的確是一個std::shared_ptr
// C API
FontHandle getFont();
void releaseFont(FontHanle fh);
class Font {
public:
explicit Font(FontHandle fh) : f(fh) { }
~Font() { releaseFont(f); }
FontHandle get() const { return f; } //顯示轉(zhuǎn)換函數(shù)
private:
FontHandle f;
};
void changeFontSize(FontHandle f, int newSize);
Font f(getFont());
int newFontSize;
...
changeFontSize(f.get(), newFontSize); //調(diào)用顯示轉(zhuǎn)換
頻繁調(diào)用時到處要求顯示轉(zhuǎn)換,使人們倒盡胃口。另一個方法是提供隱式轉(zhuǎn)換函數(shù)。
class Font {
public:
...
operator FontHandle() const { return f;} //隱式轉(zhuǎn)換函數(shù)
...
};
Font f(getFont());
int newFontSize;
...
chageFontSize(f, newFontSize); //調(diào)用隱式轉(zhuǎn)換
這個隱式轉(zhuǎn)換增加錯誤發(fā)生機會。如客戶可能會在需要Font的時候意外創(chuàng)建了一個FontHandle:
Font f1(getFont());
...
FontHandle f2 = f1; //原意是要拷貝一個Font,現(xiàn)在卻將f1隱式轉(zhuǎn)換成FontHandle后復制它
上面程序有個FontHandle由Font對象f1管理,但那個FontHandle也可以通過直接使用f2獲得。當f1被銷毀時,字體被釋放,而f2因此成為野指針。
請記住:
APIs往往是訪問原始資源 ,所以每一個RAII class應該提供一個“獲取其所管理之資源”的辦法。
對原始資源的訪問可能經(jīng)由顯示轉(zhuǎn)換或隱式轉(zhuǎn)換,一般而言顯式轉(zhuǎn)換比較安全,但是隱式轉(zhuǎn)換對客戶比較方便。
條款16:成對使用new和delete時要采取相同形式?std::string* stringArray = new std::string[100];
...
delete stringArray;
當使用new的時候,有兩個事情會發(fā)生。第一,內(nèi)存被分配出來;第二,針對此內(nèi)存會有一個(或更多)的構(gòu)造函數(shù)被調(diào)用。當使用delete的時候,也有兩件事發(fā)生。第一,針對此內(nèi)存的一個(或更多)的析構(gòu)函數(shù)被調(diào)用;第二,內(nèi)存被釋放。delete的大問題在于:即將被刪除的內(nèi)存之內(nèi)究竟有多少對象?換句話說就是即將被刪除的指針是單一對象還是對象數(shù)組。
std::string* stringPtr1 = new std::string;
std::string* stringPtr2 = new std::string[100];
...
delete stringPtr1;
delete []stringPtr2;
請記?。?/p>
如果在new表達式中使用[],必須在相應的delete表達式中使用[]。
如果在new表達式中不使用[],一定不要在相應的delete表達式中使用[]。
條款17:以獨立的語句將newed對象置入智能指針假設有兩個函數(shù)
//處理程序的優(yōu)先權(quán)
int priority();
//在動態(tài)分配的Widget上進行帶有優(yōu)先權(quán)的處理
void processWidget(std::shared_ptrpw, int priority);
processWidget(new Widget, priority());
//無法通過編譯,參數(shù)需要shared_ptr對象, Widget構(gòu)造函數(shù)是個expliclit的,無法進行隱式轉(zhuǎn)換
processWidget(std::shared_ptr(new Widget), priority());
于是在調(diào)用processWidget函數(shù)之前,編譯器必須創(chuàng)建代碼,做一下三件事:調(diào)用priority函數(shù),執(zhí)行new Widget,調(diào)用std::shared_ptr構(gòu)造函數(shù)。C++編譯器以什么樣的次序完成這幾件事呢?可以肯定的是new Widget一定執(zhí)行于std::shared_ptr構(gòu)造函數(shù)前,但priority函數(shù)則可以排在第二或第三執(zhí)行。如果編譯器選擇以第二順位執(zhí)行它,萬一priority函數(shù)發(fā)生異常,new Widget返回的指針將會遺失,因為它尚未被置入std::shared_ptr內(nèi),可能引發(fā)內(nèi)存泄漏。通常解決辦法如下:
std::shared_ptrpw(new Widget);
processWidget(pw, priority());
請記住:
以獨立的語句將newed對象存儲于(置入)智能指針內(nèi)。如果不這樣做,一旦有異常被拋出,有可能導致難以察覺的資源泄漏。
你是否還在尋找穩(wěn)定的海外服務器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務器高可用性,企業(yè)級服務器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
網(wǎng)站名稱:EffectiveC++(3)——資源管理-創(chuàng)新互聯(lián)
當前地址:http://jinyejixie.com/article0/djecio.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供域名注冊、企業(yè)網(wǎng)站制作、微信公眾號、網(wǎng)站建設、移動網(wǎng)站建設、網(wǎng)頁設計公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容