C++標准模板庫是由Alexander Stepanov、Meng Lee和David R Musser在惠普實驗室工作時所開發出來的,C++標准模板庫在C++中的應用十分廣泛,這項技術在引進C++之前已經使用很久了。
我們會假設一個失敗的資源分配會導致一個異常--事實上,這會經常的發生。所以如果你想試圖用一個石頭打兩只鳥的話,或者在一個構造函數中申請兩種形式的資源,你可能就會陷入麻煩。
只要想想在一種資源分配成功但另一種失敗拋出異常時會發生什麼。因為構造函數還沒有全部完成,析構函數不可能被調用,第一種資源就會發生洩露。這種情況可以非常簡單的避免。無論何時你有一個需要兩種以上資源的類時,寫兩個笑的封裝器將它們嵌入你的類中。每一個嵌入的構造都可以保證刪除,即使包裝類沒有構造完成。
我們至今還沒有討論最常見類型的資源--用操作符new分配,此後用指針訪問的一個對象。我們需要為每個對象分別定義一個封裝類嗎?事實上,C++標准模板庫已經有了一個模板類,叫做auto_ptr,其作用就是提供這種封裝。我們一會兒在回到auto_ptr。)讓我們從一個極其簡單、呆板但安全的東西開始。看下面的Smart Pointer模板類,它十分堅固,甚至無法實現。
- class Lock
- {
- public:
- Lock (CritSect& critSect)
- : _critSect (critSect)
- {
- _critSect.Acquire ();
- }
- ~Lock ()
- {
- _critSect.Release ();
- }
- private
- CritSect & _critSect;
- };
- 鎖一般的用法如下:
- void Shared::Act () throw (char *)
- {
- Lock lock (_critSect);
- // perform action -- may throw
- // automatic destructor of lock
- }
為什麼要把SPtr的構造函數設計為protected呢?如果我需要遵守第一條規則,那麼我就必須這樣做。資源--在這裡是class T的一個對象--必須在封裝器的構造函數中分配。但是我不能只簡單的調用new T,因為我不知道T的構造函數的參數。
因為,在原則上,每一個T都有一個不同的構造函數;我需要為他定義個另外一個封裝器。C++標准模板庫的用處會很大,為每一個新的類,我可以通過繼承SPtr定義一個新的封裝器,並且提供一個特定的構造函數。
同樣的,你也可以再你的代碼中用加強Release的可靠性。相應的Pop方法要做些什麼呢?他應該釋放了資源並祈禱調用它的是一個負責的人而且立即作一個資源傳遞它到一個Smart Pointer?這聽起來並不好。
資源管理在內容索引Windows NT Server上的一部分,現在是Windows 2000)上工作,並且,我對這十分滿意。然後我開始想……這一方法是在這樣一個完整的系統中形成的,如果可以把它內建入語言的本身豈不是一件非常好?我提出了強指針Strong Pointer)和弱指針(Weak Pointer)。
一個Strong Pointer會在許多地方和我們這個SPtr相似--它在超出它的作用域後會清除他所指向的對象。資源傳遞會以強指針賦值的形式進行。也可以有Weak Pointer存在,它們用來訪問對象而不需要所有對象--比如可賦值的引用。
任何C++標准模板庫都必須聲明為Strong或者Weak,並且語言應該來關注類型轉換的規定。例如,你不可以將Weak Pointer傳遞到一個需要Strong Pointer的地方,但是相反卻可以。Push方法可以接受一個Strong Pointer並且將它轉移到Stack中的Strong Pointer的序列中。Pop方法將會返回一個Strong Pointer。把Strong Pointer的引入語言將會使垃圾回收成為歷史。