十三、以對象管理資源
這裡用兩個智能指針做示範
class Investment
{
Initialization* CreateInvetment(); //
}
void f()
{
Initialization* pInv = CreateInvetment(); // 調用 factory函數
...
delete pInv; // 釋放pInv
}
上述代碼中,在建立指針和删除指針之間,有可能會因為種種原因(比如後人維護代碼過程中,執行了return語句),造成delete沒有被執行
解決辦法是以對象管理資源
void f()
{
std::auto_ptr<Initialization> pInv(CreateInvetment());
}
以對象管理資源的兩個關鍵技術思想
1、擷取到資源後立即放進管理對象
2、管理對象運用析構函數確定資源被釋放
注意;受auto_ptr管理的資源必須絕對沒有一個以上的auto_ptr同時指向它
舉例:
std::auto_ptr<Initialization> pInv1(CreateInvetment());
std::auto_ptr<Initialization> pInv2(pInv1); // pInv2 指向對象,pInv1被設定為NULL
pInv1 = pInv2; // pInv1指向對象,pInv2被設定為NUL
L
引用計數型指針 RCSP (reference-counting smart pointer),RSCP也是個智能指針,持續追蹤共有多少個
對象指向某筆資源,并在無人通路它的時候自動删除該資源
void f()
{
std::tr1::shared_ptr<Initialization> pInv(CreateInvetment());
std::shared_ptr<Initialization> pInv2(pInv1); // pInv1和pInv2指向同一對象
pInv1 = pInv2; // pInv1和pInv2指向同一對象}
總結:
1、為了防止資源洩漏請使用RALL對象,它們在構造函數中獲得資源并在析構中釋放資源
2、兩個常備使用的RALL call是突然::shared_ptr 和auto_ptr。前者
十四、在資源管理類中小心Coping行為
RALL (Resource Acquisition is Initialization),适用于heap-based資源上
但是并非所有的資源都是heap-based,對于這類資源,auto_ptr和tr1::shared_ptr這樣的隻能指針往往不适合作為資源管理者
在這種情況下,需要建立自己的資源管理類
總結:
在自己的資源管理類中,如果不希望發生對象的複制行為,将設定複制函數為private
十五、對原始資源的通路
顯示轉換和隐式轉換
隐式轉換就是不帶轉換類型的轉換,如int轉float你可以這樣子float a ;int b = 4;
a=b就是隐式轉換,而a = (float)b就是顯示轉換
總結:
1、API 往往要求通路原始資源,是以每一個RALL類應該提供一個"取得其所管理資源"的辦法
2、對原始資源的通路,可能經由顯式轉換或者隐式轉換,一般而言顯式轉換更安全,但隐式轉換對客戶來說更友善
十六、承兌使用new和delete是要采取相同形式
當你使用了一個 new 表達式(也就是說,通過使用 new 動态建立一個對象),有兩件事情會發生。首先,配置設定記憶體
(通過一個被稱為 operator new 的函數——參見 Item 49 和 51)。第二,一個或多個構造函數在這些記憶體上被調用。
當你使用一個 delete 表達式(也就是說,使用 delete),有另外的兩件事情會發生:一個或多個析構函數在這些記憶體上被調用,
然後記憶體被回收
new[]出來的對象,用delete釋放,可能隻釋放了一部分,
new出來的對象,用delete[]釋放,可能将一塊記憶體釋放很多次
總結:
new\delete對應,和new[]\delete[] 對應
十七、在一個獨立的語句中,将new出來的對象存入隻能指針
"為什麼要這麼做?不這麼做會怎樣"
場景:
int priority();
void processWidget(std::st1::shared_ptr<Widget> pw,int ipriority());
A、
<1>、調用priority
<2>、執行"new Widget"
<3>、調用tr1::shared_ptr構造函數
B、
<1>、執行"new Widget"
<2>、調用priority
<3>、調用tr1::shared_ptr構造函數
shd::tr1::shared_ptr<Widget> pw(new Widget);
processWidget(pw,ipriority());