More C++ Idioms/コピーして swap(Copy-and-swap)
表示
コピーして 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 イディオムを参照。
};