Effective C++之二十五

      要点:提供不会抛出异常的swap函数。

      swap自STL引入后就成为异常安全(exception-safe)编程的基石。在条款11避免自赋值时已谈到过。

      STL中swap的缺省实现是通过临时变量实现交换。但是对某些类型这是很低效的,例如pimpl只需要交换指针即可。

      之后,Meyers提出在std命名空间内特例化函数模板swap的实现。由于函数模板中不能访问private成员变量,因此类需要提供public成员函数swap实现交换功能,供函数模板调用。

      进而,Meyers提出如果Widget不是类而是类模板的情况。由于C++不允许部分特例化函数模板(C++允许部分特例化类模板),因此套用普通类的swap实现是错误的。一般情况,可以重载函数模板,但是由于std的特殊性,不允许向std中增加新的模板(向std增加新模板可以编译和运行,但是其行为是未定义的)。

      最后,Meyers提出的解决方案是:定义函数模板,但是不重载或特例化std::swap。这样,根据Koenig查找规则就能找到这个swap函数。这个解决方案看似对类和类模板均可行,但是为了让类的特别版swap在尽可能多的环境下有效,对类应采用特例化std::swap的方法。

     

      然后,Meyers提出从客户代码调用swap的角度的情况。在doSomething的例子中,swap调用的是通用的std::swap(肯定存在),还是特例化的std::swap(可能不存在),还是在全局命名空间或者T所在命名空间内的T类型特殊版swap(可能不存在)呢? 根据Koeing规则,首先查找命名空间内的T特殊版swap,如果没有找到则采用std::swap(该函数由using引入);在使用std:swap时,如果存在优先使用特例化的std::swap函数。Meyers还特别指出不能对swap采用std::限定,因为这样会阻止编译器使用全局或T所在命名空间中特别版的swap函数。

      

     总结

     1) 首先看std::swap缺省实现的效率是否可接受。如果不可行,则2

     2) 定义public无抛出异常的swap函数实现交换功能

     3) 在同一命名空间,定义非成员函数模板swap,实现中调用成员swap函数

     4) 如果定义的是类(不是类模板),则特例化std::swap,实现中调用成员swap函数。

 

     要求成员函数swap不抛出异常,是因为swap被用于确保强异常安全(参见条款29)。强异常安全仅对成员函数swap有效,因为缺省std::swap中使用到copy构造和赋值函数,两种均可能抛出异常。因此,类特殊版的swap不仅提高效率,还提供了异常安全性。

 

      附:

      - Koening规则可参见Exceptional C++条款31和32

      - C++ Template 9.2.1 ADL 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值