91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

《Effective C++》 讀書筆記之三 資源管理

發布時間:2020-08-02 10:51:18 來源:網絡 閱讀:311 作者:313119992 欄目:編程語言

《Effective C++》 讀書筆記之三 資源管理

準備知識:

  1. 所謂資源就是,一旦用了它,將來必須還給系統。最常用的資源是動態分配內存,其他常見的資源有文件描述器、互斥鎖、圖形界面的字形和筆刷、數據庫連接以及網絡sockets。

  2. auto_ptr 是個“類指針對象”,就是所謂的智能指針,其析構函數自動對其所指對象調用delete。auto_ptr位于 #include <memory> 頭文件。由于auto_ptr被銷毀時會自動刪除它所指之物,所以一定要注意別讓多個auto_ptr指向同一個對象。auto_ptr有個不尋常的性質:若通過copy構造函數或copy assignment操作符復制它們,它們會變成null,而復制所得的指針將取得資源的唯一擁有權。auto_ptr并非管理動態分配資源的神兵利器。

  3. Reference-counting smart pointer(引用計數型智慧指針RCSP)是auto_ptr的一種替代方案。持續追蹤共有多少對象指向某筆資源,并在無人指向它時自動刪除。RCSPs提供的行為類似垃圾回收,不同的是,RCSPs無法打破環狀引用(例如兩個其實已經沒有被使用的對象彼此互指,因而好像還處于“被使用”狀態)。

  4. TR1的tr1::shared_ptr 是一個RCSP。

  5. auto_ptr和tr1::shared_ptr兩者都在其析構函數內做delete而不是delete[]動作。那意味著動態分配而得的array身上使用auto_ptr或tr1::shared_ptr是不明智的。但是這是可以通過編譯的。

//準備知識2 auto_ptr不尋常的性質

std::auto_ptr<Investment> pInv(createInvestment());
//pInv指向createInvestment()返回物
std::auto_ptr<Investment> pInv2(pInv);
//現在pInv2指向對象,pInv被置為null
pInv = pInv2;
//現在pInv指向對象,pInv2被置為null



正文


條款13:以對象管理資源 Use objects to manage resource

獲取資源后立刻放進管理對象內。(資源取得時機便是初始化時機。Resource Acquisition Is Initialization;簡稱RAII)

管理對象運用析構函數確保資源被釋放。

例子如下:

class Investment{...};
Investment* createInvestment();

void f()//auto_ptr版本
{
	std::auto_ptr<Investment> pInv(createInvestment());
	// 調用factory函數,使用pInv經由auto_ptr的析構函數自動刪除pInv
	...
}


void f()//shared_ptr版本
{
	...
	std::tr1::shard_ptr<Investment> pInv(createInvestment());
	//pInv指向createInvestment()返回物
	std::tr1::shard_ptr<Investment> pInv2(pInv);
	//現在pInv,pInv2指向同一對象
	pInv = pInv2;
	//無任何改變
	...
}


重點:

  1. 為防止資源泄漏,請使用RAII對象,它們在構造函數中獲得資源并在析構函數中釋放資源。

  2. 兩個常用的RAII classes 分布式tr1::shared_ptr 和auto_ptr。前者通常是較佳選擇,因為其copy行為比較直觀。若選擇auto_ptr,復制動作會使它指向null。

2016-11-03 22:23:43


條款14:在資源管理類中小心copying行為。

當一個RAII對象被復制,有如下幾種可能

  1. 禁止復制。

    class Lock:private Uncopyable{ };

  2. 對底層資源祭出“引用計數法”。有時候我們希望保有資源,直到它的最后一個使用者被銷毀。這種情況下復制RAII對象時,應該將資源的“被引用數”遞增。tr1::shared_ptr便是如此。tr1::shared_ptr允許指定所謂的“刪除器”,那是一個函數或函數對象,當引用次數為0時便被調用。刪除器對tr1::shared_ptr構造函數而言是可有可無的第二參數。

  3. 復制底部資源。進行深度拷貝。

  4. 轉移底部資源的擁有權。采用auto_ptr。

class Lock{
public:
    //以某個Mutex初始化shared_ptr,并以unlock函數作為刪除器
    explicit Lock(Mutex *pm):mutexPtr(pm,unlock)
    {
        lock(mutexPtr.get());
    }
private:
    std::tr1::shared_ptr<Mutex> mutexPtr;
}


重點:

  1. 復制RAII對象必須一并復制它所管理的資源,所以資源的copying行為決定RAII對象的copying行為。

  2. 普通而常見的RAII class copying行為是:抑制copying、施行引用計數法。不過其他行為也都可能被實現。

2016-11-03 23:59:30

條款15:在資源管理類中提供對原始資源的訪問。

有時候需要一個函數可將 RAII class 對象轉換為其所內含之原始資源。有兩種做法可以達成目標:

1.顯式轉換

tr1::shared_ptr和auto_ptr都提供一個get成員函數,用來執行顯式轉換,也就是它會返回智能指針內部的原始指針。

例子如下:

std::tr1::shared_ptr<Investment> pInv(createInvestment());

int daysHeld(const Investment* pi);

int days = daysHeld(pInv);//錯誤!!! 不允許直接使用智能指針,需要獲取原始資源。

int days = daysHeld(pInv.get());//good!!!將pInv內的原始指針傳給daysHeld


2.隱式轉換

幾乎所有的智能指針都重載了指針取值操作符(operator->和operator*),tr1::shared_ptr和auto_ptr也重載了取值操作符,它們允許隱式轉換至底部原始指針。

例子如下:

class Investment{
public:
	bool isTaxFree() const;
	...
};

Investment* createInvestment();
std::tr1::shared_ptr<Investment> pi1(createInvestment());
bool taxable1 = !(pi1->isTaxFree());//經過operator->訪問資源

std::tr1::shared_ptr<Investment> pi2(createInvestment());

bool taxable2 = !((*pi1).isTaxFree());//經過operator*訪問資源


重點:

  1. APIs往往要求訪問原始資源,所以每一個RAII class應該提供一個“取得所管理之資源”的辦法。

  2. 對原始資源的訪問可能經由顯式轉換或隱式轉換。一般而言顯式轉換比較安全,但隱式轉換對客戶比較方便。

2016-11-04 17:44:52

條款16:成對使用new和delete時要采取相同形式。

當你使用new,有兩件事發生。第一,通過operator new的函數內存被分配出來。第二,針對此內存會有一個構造函數被調用。

當你使用delete,有兩件事發生。第一,針對此內存會有一個(或多個)析構函數調用。第二,通過operator delete的函數釋放內存。

delete的最大問題在于:即將被刪除的內存之內究竟存有多少個對象?

當你對一個指針使用delete,唯一能夠讓delete知道內存中是否存在一個“數組大小記錄”的辦法就是:由你來告訴它。如果你使用delete時加上中括號[],delete便認定指針指向一個數組,否則它便認定指針指向單一對象。

例子如下:

std::string* stringPtr1 = new std::string;
std::string* stringPtr2 = new std::string[100];
...
delete stringPtr1;//刪除一個對象
delete [] stringPtr2;//刪除一個由對象組成的數組


盡量不要對數組形式做typedefs動作。可以使用vector或者string來替代。

重點:

如果你在使用new表達式中使用[],必須在相應的delete表達式中也使用[]。如果你在使用new表達式中不使用[],一定不要在相應的delete表達式中使用[]。

2016-11-04 17:54:51


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

例子:

int priority();
void processWidget(str::tr1::shared_ptr<Widget> pw,int priority);

調用processWidget:

processWidget(new Widget,priority());//不能通過編譯
processWidget(std::tr1::shared_ptr<Widget> (new Widget),priority());//可以通過編譯

調用processWidget之前,編譯器必須創建代碼,做一下3件事:

1.調用priority;

2.執行“new Widget”;

3.調用tr1::shared_ptr構造函數。


由于C++編譯器以什么樣的次序完成這件事,彈性很大。

一種可能的操作順序是2,1,3。但是在執行2后,如果執行1時,發生異常,那么2中返回的指針被遺失。

而且3還沒有來得及執行,所以2返回的指針沒有置入st1::shared_ptr內,所以會發生資源泄漏。


避免這類問題的辦法很簡單:使用分離語句。分別寫出(1)創建Widget;

(2)將它置于一個智能指針內,然后再把那個智能指針傳給processWidget:

std::tr1::shared_ptr<Widget> pw(new Widget);
processWidget(pw,priority());


重點:

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

2016-11-04 22:56:02

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

平罗县| 安义县| 会泽县| 永修县| 鄢陵县| 隆化县| 定西市| 五莲县| 龙山县| 延吉市| 大邑县| 饶河县| 思茅市| 吕梁市| 井冈山市| 亚东县| 包头市| 华蓥市| 道孚县| 旬邑县| 沾益县| 紫金县| 平南县| 宁阳县| 临沭县| 五原县| 山西省| 仲巴县| 昌乐县| 洞头县| 西和县| 双流县| 娄烦县| 大悟县| 叶城县| 泌阳县| 恭城| 谷城县| 观塘区| 淳安县| 广水市|