More C++ Idioms/コピーして swap(Copy-and-swap)
出典: フリー教科書『ウィキブックス(Wikibooks)』
目次 |
[編集]
コピーして swap(Copy-and-swap)
[編集] 意図
オーバーロードされた代入演算子の例外安全な実装を作成する。
[編集] 別名
[編集] 動機
例外安全性は、例外を「例外的な」状況を示すために用いるような、高い信頼性のある C++ ソフトウェアにとって非常に重要な基礎となる。 少なくとも 3 つの例外安全性のレベルがある。基本例外安全、強い例外安全、例外中立である。 基本例外安全は、大抵低コストで実装できるのでいつでも提供されるべきである。 強い例外安全を保証することは、全ての場合で可能ではないかもしれない。 コピーして swap(Copy-and-swap)イディオムは強い例外安全な代入演算子を簡潔に実装する。
[編集] 解法とサンプルコード
コピーして swap(Copy-and-swap)イディオムは、現在のリソースが回収される前に新しいリソースを獲得する。 新しいリソースを獲得するために、RAII イディオムを用いる。 新しいリソースの獲得に成功すれば、throw しない swap(non-throwing swap)イディオムを用いて、リソースの交換を行う。 最後に、最初のステップの RAII の副作用により古いリソースが解放される。
class String { public: String & operator = (String const &s) { String temp (s); // コピーコンストラクタ -- RAII temp.swap (*this); // throw しない swap return *this; }// temp のデストラクタが呼び出されたときに古いリソースが解放される。 void swap (String &s) throw (); /// thow しない swap イディオムを参照。 };
上記実装の変種もありうる。 自己代入のチェックは厳密には必要ではないが、いくらかの性能向上はあり得る。
class String { public: String & operator = (String const &s) { if (this != &s) String(s).swap (*this); // コピーコンストラクタと throw しない swap return *this; }// 古いリソースはここで解放される。 void swap (String &s) throw (); /// throw しない swap イディオムを参照。 };