Effective C++读书笔记之考虑写出一个不抛异常的swap函数

swap是个有趣的函数。原本它只是STL的一部分,可是它成为异常安全性编程的脊柱,以及用来处理自我赋值的一个常见机制。可以看到swap函数的重要性。所以我们要讨论一下它的复杂度。
 缺省情况下swap是由标准程序库提供的swap算法完成的,如下:
 namespace std {
  template<typename T>        //std::swap的典型实现
  void swap(T& a, T&b)
  {
   T temp(a);
   a = b;
   b = temp;
  }
 }
 只要类型T支持copying(通过copy构造函数和copy assignment操作符完成),上面的代码就会帮你置换类型为T的对象。
 一些时候我们需要为我们自己的类型提供特化的swap函数,因为std中的swap可能对这些类型效率不好。
 1) 当我们的类型的数据成员是一个指针,而这个指针指向一个含有真正数据的对象时,使用标准的swap交换这样的对象时,它不仅要复制三个这个类的对象,还要复制三个类中指针所指类的对象,效率很差。而实际上只要交换两个对象中的指针就可以。所以我们为这样的类型提供特化的swap函数。举个例子说明:
 class Widget {         //我们自己的类型
 public:
  Widget(const Widget& rhs);
  Widget& operator=(cosnt Widget& rhs);  //注意复制Widget时,复制的是WidgetImpl对象
 private:
  WidgetImpl* pImpl;   //指针,所指对象内含Widget数据
 };
 解决方法:将std::swap针对Widget特化。通常我们不能够(不被允许)改变std命名空间内的任何的东西,但可以(被允许)为标准templates(如swap)制造特化版本,使它专属于我们自己的classes。
 我们令Widget声明一个名为swap的public成员函数做真正的置换工作,然后将std::swap特化,令它调用该成员函数。
 class Widget {         //与前相同,就是增加了swap函数
 public:
  ....
  void swap(Widget& other)
  {
   using std::swap;         
   swap(pImpl, other.pImpl);   若要置换Widgets就置换其pImpl指针
  }
  ....
 };
 namespace std {
  template<>   //template<>表示它是std::swap的一个全特化版本
  void swap<Widget>(Widget& a, Widget& b)  //<Widget>表示这一特化版本针对"T是Widget"而设计的
  {                                        //也就是说一般性的swap template施行于Widgets身上便会使用这个版本
   a.swap(b);
  }
 }
 上面的做法还与STL容器在一致性,因为所有STL容器也都提供有public swap成员函数和std::swap特化版本(用以调用前者)
 简单的了解了一下上面的代码后,我们整理一下思路:
 首先,如果swap的缺省实现的代码对你的class或class templates提供可接受的效率,你不需要额外做任何事。
 其次,如果swap的缺省实现版本的效率不足,试着做以下的事情:
 1) 提供一个public swap成员函数,让它高效的置换你的类型的两个对象值。
 2) 在你的class或class template所在的命名空间提供一个non-member swap,并令它调用上述swap成员函数
 3) 如果你正编写一个class而非class template,为你的class特化std::swap。并令它调用你的swap成员函数
 总结:
 1) 当std::swap对你的类型效率不高时,提供一个swap成员函数,并确定这个函数不抛出异常
 2) 如果你提供一个member swap,也该提供一个non-member swap用来调用前者。对于classes而非templates,也请特化std::swap
 3) 调用swap时应针对std::swap使用using声明式,然后调用swap并且不带任何命名空间资格修饰
 4) 为用户定义类型进行std templates全特化是好的,但千万不要尝试在std内加入某些对std而言全新的东西 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值