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)

相关原语 编辑

参考资料 编辑