條款25 考慮寫出乙個不丟擲異常的swap函式

2021-06-28 05:09:04 字數 2538 閱讀 3740

swap原本只是stl的一部分,後面成為異常安全程式設計的脊柱,及處理自我賦值安全性的乙個常見機制。

例子:標準程式庫提供的swap演算法

namespace s td

}

要求:型別t支援copying(通過copying建構函式和copyassignment操作符完成)

上述**主要涉及三個物件的複製,但對於某些型別而言,複製並不重要。

如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...