swap原本只是stl的一部分,後面成為異常安全程式設計的脊柱,及處理自我賦值安全性的乙個常見機制。要求:型別t支援copying(通過copying建構函式和copyassignment操作符完成)例子:標準程式庫提供的swap演算法
namespace s td
}
上述**主要涉及三個物件的複製,但對於某些型別而言,複製並不重要。
如pimpl手法(point to implementation)」以指標指向乙個物件,內含真正資料」
class widgetimpl //針對widget設計的類;
class widget //採用pimpl手法
private:
widgetimpl*impl; //指標,內含widget資料
};
轉換述物件,只需置換pimpl指標,相對比複製物件效率更高。
為了讓std::swap知道置換widget時是置換指標pimpl,可行的方法是將std::swap針對widg特化,如下構想。
namespace std
}
「template<>」表明它是std::swap的乙個全特化版本(total template specialization),函式名後的
表示這一特化版本是針對「t是
widget
」而設計。(一般性的swap施行於widget便會啟用這個版本)
通常不允許改變
std命名空間內的任何東西,但允許為標準的templates(如swap)製造特化版本,使它專屬於某個類(如widget)
上述不編譯不能過,我們可以置其為友員。
還有解決方法是:令widget宣告乙個名為swap的public成員函式做真正的置換工作。然後將std::swap特化,令它呼叫該成員函式,如下:
class widget //同前,唯一差別是增加了swap
...};namespace std
}
這種作法能通過編譯,還與stl有一至性:因為所有
stl容器提供有
public swap
成員函式和
std::swap
的特化版本。
當是類模版而非類時,如下**:
templateclasswidgetimpl;
templateclasswidget;
namespace std
}
看似合理,實則錯誤。因為上面我們企圖偏特化
(partially specialize)
乙個函式模板(function template(std::swap)),c++僅允許對類模板偏特化。
當偏化乙個函式模版時,慣常做法是簡單的函式過載,如下**,但是也是不合法的、
namespace std //std::swap的乙個過載版本
}
一般過載函式模版沒問題,但std是特殊的命名空間。標準委員會禁止膨脹那些已經宣告好的東西。也就是說:我們可以全特化
std內的
template,
但不能新增任何新的東西(模版或class或functions等)。
解決方法:宣告乙個non-member的swap呼叫member swap,但不再將non-member宣告為std::swap的特化或過載版本。假設所有widger機能位於名字空間widgetstuff內,如下**:
namespacewidgetstuff
; //類含swap成員函式
templatevoidswap>(widget& a,widget& b)
//非成員函式,但不屬於std空間
}
現在任何地點置換兩個widget物件,c++會根據名稱查詢法則(name lookuprule)找到widgetstuff內專屬版本。
如果想讓「class專屬版」swap在更多情況下適用,應在該class所在命名空間內寫乙個non-menber版本和std::swap特化版本
對於default swap,member swap, non-member swaps,std::swap特化版本做個總結:
如果預設swap效率好,則使用預設swap,反之,則、
1、提供乙個public成員函式,高效轉換物件值。(但這個函式絕不能丟擲異常)
2、如果提供乙個member swap,也應該提供乙個non-memberswap來呼叫前者。對class(而非類模版),特化std::swap。
3、呼叫swap時應針對std::swap使用using 宣告式,然後呼叫swap不帶任何「命名空間資格修飾符」。
4、對「使用者定義型別」進行
stdtemplate
全特化。但不能在
std內加入全新東西。
條款25 考慮寫出乙個不丟擲異常的swap函式
首先本篇部落格的主要思想是 系統自帶的swap函式有時候不能滿足我們的需求,所以在一些情況下我們就需要自己去寫swap函式。此條款的主要內容就是告訴你該如何去寫你要的swap函式,下面開始正文來好好地介紹一下此條款的內容 1.首先來看一下庫裡面給的swap函式的原型 可以看出來標準程式庫提供的swa...
條款25 考慮寫出乙個不拋異常的swap函式
總結 如果 std swap 對於你的型別來說是低效的,請提供乙個 swap 成員函式,並確保你的 swap 不會丟擲異常。如果你提供乙個成員 swap,請同時提供乙個呼叫成員swap的非成員swap。對於類 非模板 還要特化 std swap。呼叫swap時,請為std swap使用乙個using...
考慮寫出乙個不丟擲異常的swap函式
1 當std swap對你的型別效率不高時,提供乙個swap成員函式,並確定這個函式不丟擲異常。2 如果你提供乙個member swap函式,也該提供乙個non member swap函式,後者用來呼叫前者。對於class 而非template 也請特化std swap 3 呼叫swap時應針對st...