EffectiveC++(3)——資源管理-創(chuàng)新互聯(lián)

條款13:以對象管理資源(RAII)
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)品牌建設(shè)與網(wǎng)絡(luò)營銷,包括成都網(wǎng)站設(shè)計、成都網(wǎng)站建設(shè)、外貿(mào)網(wǎng)站建設(shè)、SEO優(yōu)化、網(wǎng)絡(luò)推廣、整站優(yōu)化營銷策劃推廣、電子商務(wù)、移動互聯(lián)網(wǎng)營銷等。創(chuàng)新互聯(lián)公司為不同類型的客戶提供良好的互聯(lián)網(wǎng)應(yīng)用定制及解決方案,創(chuàng)新互聯(lián)公司核心團隊十載專注互聯(lián)網(wǎng)開發(fā),積累了豐富的網(wǎng)站經(jīng)驗,為廣大企業(yè)客戶提供一站式企業(yè)網(wǎng)站建設(shè)服務(wù),在網(wǎng)站建設(shè)行業(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ù)制,會發(fā)生什么?

Lock ml1(&m);
Lock ml2(ml1);

大多數(shù)情況,會選擇以下兩種可能:

  • 禁止復(fù)制。將copying操作聲明為private。
class Uncopyable {
protected:
    Uncopyable() {}
    ~Uncopyable() {}
private:
    Uncopyable(const Uncopyable &);
    Uncopyable& operator=(const Uncopyable &);
};

class Lock : private Uncopyable {
public:
    ...
};
  • 對底層資源祭出“引用計數(shù)法”。不再聲明析構(gòu)函數(shù),std::shared_ptr在引用計數(shù)為0時自動調(diào)用shared_ptr的刪除器。
class Lock {
public:
? ? explicit Lock(Mutex *pm) : mutexPtr(pm, unlock) {
? ? ? ? lock(mutexPtr.get());
? ? }

private:
? ? std::shared_ptrmutexPtr;
};

請記住:

復(fù)制RAII對象必須一并復(fù)制它所管理的資源;

普遍而常見的RAII classcopying行為是:抑制copying、實施引用計數(shù)法。

條款15:在資源管理類中提供對原始資源的訪問
std::shared_ptrpInv(createInverstment());

int daysHeld(const Inverstment* pi);

int days = daysHeld(pInv);    //無法通過編譯

daysHeld需要時Inverstment*指針,傳給它的確是一個std::shared_ptr的對象??梢杂脙煞N方法達(dá)成轉(zhuǎn)換:顯式轉(zhuǎn)換和隱式轉(zhuǎn)換。

// 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后復(fù)制它

上面程序有個FontHandle由Font對象f1管理,但那個FontHandle也可以通過直接使用f2獲得。當(dāng)f1被銷毀時,字體被釋放,而f2因此成為野指針。

請記?。?/p>

APIs往往是訪問原始資源 ,所以每一個RAII class應(yīng)該提供一個“獲取其所管理之資源”的辦法。

對原始資源的訪問可能經(jīng)由顯示轉(zhuǎn)換或隱式轉(zhuǎn)換,一般而言顯式轉(zhuǎn)換比較安全,但是隱式轉(zhuǎn)換對客戶比較方便。

條款16:成對使用new和delete時要采取相同形式?
std::string* stringArray = new std::string[100];
...
delete stringArray;

當(dāng)使用new的時候,有兩個事情會發(fā)生。第一,內(nèi)存被分配出來;第二,針對此內(nèi)存會有一個(或更多)的構(gòu)造函數(shù)被調(diào)用。當(dāng)使用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表達(dá)式中使用[],必須在相應(yīng)的delete表達(dá)式中使用[]。

如果在new表達(dá)式中不使用[],一定不要在相應(yīng)的delete表達(dá)式中使用[]。

條款17:以獨立的語句將newed對象置入智能指針

假設(shè)有兩個函數(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());

請記?。?/p>

以獨立的語句將newed對象存儲于(置入)智能指針內(nèi)。如果不這樣做,一旦有異常被拋出,有可能導(dǎo)致難以察覺的資源泄漏。

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧

網(wǎng)站名稱:EffectiveC++(3)——資源管理-創(chuàng)新互聯(lián)
當(dāng)前地址:http://muchs.cn/article0/djecio.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供域名注冊企業(yè)網(wǎng)站制作、微信公眾號、網(wǎng)站建設(shè)、移動網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計公司

廣告

聲明:本網(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)

商城網(wǎng)站建設(shè)