More C++ Idioms/異常安全swap

維基教科書,自由的教學讀本

異常安全swap
[編輯]

意圖[編輯]

  • 實現異常安全的有效的交換操作
  • 提供便於泛型編程的一致接口

別名[編輯]

  • Non-throwing swap
  • Exception safe swap

動機[編輯]

交換的典型的實現可能是下面這樣:

template<class T>
void swap (T &a, T &b)
{
  T temp (a);
  a = b;
  b = temp;
}

這可能存在下面兩個問題:

性能
由於獲得和釋放臨時中間變量,將導致交換兩個相同類型的體積龐大的複雜對象變得非常低效。
異常安全性
如果資源不可用,swap可能會拋出異常(出現這樣的行為完全沒有任何意義,事實上沒有申請新資源的必要。)。因此這一實現不能用於拷貝複製原語。

解決方案和示例代碼[編輯]

異常安全交換原語使用Handle Body原語來完成想要的效果。問題的抽象被分為兩個具體的類,一個是handle,另一個是body。handle持有一個body的指針,交換的實現只是簡單的交換指針,這樣就可以保證不拋出任何異常,由於沒有申請釋放任何新的資源因此是非常高效的。

namespace Orange {
class String 
{
    char * str;
  public:
    void swap (String &s) // throw ()
    {
      std::swap (this->str, s.str);
    }
};
}

雖然有效的異常安全的swap函數可以實現為一個成員函數(就像上面那樣),異常安全swap原語比這個簡單的情況更加接近於泛型編程。一個顯式 std::swap 模板偏特化可以添加到 std 和該類自身的命名空間。

namespace Orange { // namespace of String
  void swap (String & s1, String & s2) // throw ()
  {
    s1.swap (s2);
  }
}
namespace std {
  template <>
  void swap (Orange::String & s1, Orange::String & s2) // throw ()
  {
    s1.swap (s2);
  }
}

已知應用[編輯]

boost 智能指針 (例如 boost::shared_ptr)

相關原語[編輯]

參考資料[編輯]