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 イディオムを参照。
};

既知の利用[編集]

関連するイディオム[編集]

References[編集]