條款29 為 異常安全 而努力是值得的

2021-04-30 08:37:43 字數 2324 閱讀 7872

條款29:為"異常安全"而努力是值得的

(strive for exception-safe code.)

內容:看了這款的內容,我對c++的難以控制的"脾氣"又有了進一步的了解,c++的安全性問題一直是廣大非c++程式

員所抨擊c++語言"惡行"的主要方面,我們今天討論的其"異常安全性"也是其複雜之處之一,看完這一款之後,你也許

會發覺你以前寫的**可能會給最終產品帶來多大的"風險隱患",廢話我就不多說了,開始進入今天的話題.

按照老規矩來,先看乙個例子:假設有個class用來表現夾帶背景圖案的gui選單,這個class也要用於多執行緒

環境當中,所以我們考慮用了乙個互斥器(mutex)作為併發控制(concurrency control)之用:

class prettymenu;

下面是乙個可能的實現:

void prettymenu::changebackground(std::istream& imgsrc)

從"異常安全性"的角度來看,這個真是個糟糕的實現版本,至少我們能夠指出如下兩點不足:(1)如果image構造

函式丟擲異常,那麼mutex_就永遠不能得到unlock;(2)此外如果構造沒有成功,而imagechangescounts_是在構造

之前執行,那麼其自然就出現了"資料失真"的風險.

解決問題(1)我們可以用物件管理資源方法進行解決(條款13中提到),我們只要把imagechangescounts_的自

增操作放在物件產生之後也就可以解決問題(2)了,該實現先修改如下:

void prettymenu::changebackground(std::istream& imgsrc)

進一步我們可以把刪除操作放在智慧型指標內部完成:

class prettymenu;

void prettymenu::changebackground(std::istream& imgsrc)

**是不是簡潔多了,呵呵.看起來這樣使得"異常安全機制"很完美嘛,不過"美中不足"的是:如果image建構函式出

現異常,那麼有可能輸入流imagesrc的讀取記號將被移走.這樣的話,該函式也只能提供"基本的異常安全保證".什麼是

"基本的異常安全保證",別急,挺我給你慢慢道來,作為異常安全函式必須提供以下三個保證之一:

■ 基本承諾:如果異常被丟擲,程式內的任何事物仍然保持在有效狀態下.

■ 強烈保證:如果異常被丟擲,程式狀態不改變.

■ 不拋擲(nothrow)保證:承諾絕不丟擲異常,因為它們總是能夠完成它們原先承諾的功能.

理解了上面三種專業屬於後,我們來把目光再次聚焦到上面changebackground的**實現上,看看現在的**

,已經很好了呀,由於先前的那個小不足,使得我的這段**還是沒有達到"異常安全的強烈保證",我不放棄,四處尋找解

決方案終於有個一般化的設計策略可以達到這個目的,這個策略被稱為"copy and swap",俗話說"名如其人",這個原則其

實就是:為你打算修改的物件儲存乙個副本,然後在該副本上修改.若修改過程中發生異常,問題不大,呵呵,因為原

物件狀態沒有被改變嘛.修改動作完成以後進行"副本與原物件互換"操作.真是個不錯的方案,我心理不由的贊乙個,下

面我們就開始改**:

struct pmimpl;

class prettymenu

private:

mutex mutex_;

std::tr1::shared_ptrpimpl_;

};nnd,**量又增多了,有得必有失嘛,想開點!我們注意到copy-and-swap的關鍵在於"修改物件資料副本,然後在

乙個不拋異常的函式中將修改後的資料和原件置換",因此必須為每乙個即將被改動的物件做乙個副本,那得耗用你

可能無法(無意願)**的時間和空間.這是乙個很實際的問題:我們都希望提供"強烈保證";當它可被實現時你的確應

該提供它,但"強烈保證"並非在任何時刻都顯得實際.當強烈保證不切實際的時候,你就必須提供基本保證.在實際的開

發當中你可以為某些函式提供強烈保證,但效率和複雜度帶來的成本會使得你不得不去放棄它,萬一實際不可行,使

你退而求其次地只提供基本保證,任何人都不該因此責難你.對許多函式而言,"異常安全性之基本保證"是乙個絕對通情達

理的選擇.

累死我了,到此結束.

請記住:

■ 異常安全函式即使發生異常也不會洩漏資源或允許任何資料結構被破壞.這樣的函式區分為三種可能的保證:

基本型、強烈型、不拋異常型.

■ "強烈保證"往往能夠以copy-and-swap實現出來,但"強烈保證"並非對所有函式都可實現或具備現實意義.

■ 函式提供的"異常安全保證"通常最高只等於其所呼叫之各個函式的"異常安全保證"中的最弱者.

條款29 避免返回內部資料的控制代碼

假設b是乙個const string物件 class string const string b hello world b是乙個const物件 看看下面的情形 char str b 呼叫b.operator char strcpy str,hi mom 修改str指向的值 b的值現在還是 hell...

C 異常安全

異常安全的 是指,滿足兩個條件 1異常中立性 是指當你的 包括你呼叫的 引發異常時,這個異常 能保持原樣傳遞到外層呼叫 2.異常安全性 一段 要具有異常安全性,必須同時具有異常中立性和一定等級的異常安全性保證 異常安全的等級一般有 1,函式提供基本保證 the basic guarantee 不會發...

條款22 將成員變數為private

條款22 將成員變數為private includeusing namespace std class accesslevedls void setreadwrite int value int getreadwrite const void setwriteonly int value priva...