Effective C 之二十五

2021-04-29 20:06:44 字數 1291 閱讀 5783

要點:提供不會丟擲異常的swap函式。

swap自stl引入後就成為異常安全(exception-safe)程式設計的基石。在條款11避免自賦值時已談到過。

stl中swap的預設實現是通過臨時變數實現交換。但是對某些型別這是很低效的,例如pimpl只需要交換指標即可。

之後,meyers提出在std命名空間內特例化函式模板swap的實現。由於函式模板中不能訪問private成員變數,因此類需要提供public成員函式swap實現交換功能,供函式模板呼叫。

進而,meyers提出如果widget不是類而是類模板的情況。由於c++不允許部分特例化函式模板(c++允許部分特例化類模板),因此套用普通類的swap實現是錯誤的。一般情況,可以過載函式模板,但是由於std的特殊性,不允許向std中增加新的模板(向std增加新模板可以編譯和執行,但是其行為是未定義的)。

最後,meyers提出的解決方案是:定義函式模板,但是不過載或特例化std::swap。這樣,根據koenig查詢規則就能找到這個swap函式。這個解決方案看似對類和類模板均可行,但是為了讓類的特別版swap在盡可能多的環境下有效,對類應採用特例化std::swap的方法。

然後,meyers提出從客戶**呼叫swap的角度的情況。在dosomething的例子中,swap呼叫的是通用的std::swap(肯定存在),還是特例化的std::swap(可能不存在),還是在全域性命名空間或者t所在命名空間內的t型別特殊版swap(可能不存在)呢? 根據koeing規則,首先查詢命名空間內的t特殊版swap,如果沒有找到則採用std::swap(該函式由using引入);在使用std:swap時,如果存在優先使用特例化的std::swap函式。meyers還特別指出不能對swap採用std::限定,因為這樣會阻止編譯器使用全域性或t所在命名空間中特別版的swap函式。

總結

1) 首先看std::swap預設實現的效率是否可接受。如果不可行,則2

2) 定義public無丟擲異常的swap函式實現交換功能

3) 在同一命名空間,定義非成員函式模板swap,實現中呼叫成員swap函式

4) 如果定義的是類(不是類模板),則特例化std::swap,實現中呼叫成員swap函式。

要求成員函式swap不丟擲異常,是因為swap被用於確保強異常安全(參見條款29)。強異常安全僅對成員函式swap有效,因為預設std::swap中使用到copy構造和賦值函式,兩種均可能丟擲異常。因此,類特殊版的swap不僅提高效率,還提供了異常安全性。

附:- koening規則可參見exceptional c++條款31和32

- c++ template 9.2.1 adl 

effective C 條款二十五解讀

考慮寫出乙個不丟擲異常的高效的swap函式 首先得說明為什麼我們要優化我們的swap函式,swap函式是異常安全性程式設計的脊柱,同時也是處理operator 自我賦值的重要手段。要編寫乙個優化版本的swap函式,我們首先需要了解標準庫是怎們定義的swap函式 namespace std 這個函式很...

python程式設計基礎之二十五

匿名函式 不用def 定義的函式,沒有函式名 lambda 引數1 引數2 引數3 引數n 表示式 def test print 我是測試函式 print test 函式名是變數,指向了函式物件 pf test pf變數也指向了函式物件,所以也可以通過pf呼叫test函式 pf 傳入函式 乙個函式接...

演算法(二十五)

1 給定兩個不字串,求出最長公共子串行的長度。int longestpublicsubsequence string x,string y else return math.max longestpublicsubsequence x.substring 1 y.substring 0 longes...